Merge master <-> api_changes
authorMatthew Vogt <matthew.vogt@nokia.com>
Mon, 5 Mar 2012 01:39:24 +0000 (11:39 +1000)
committerMatthew Vogt <matthew.vogt@nokia.com>
Mon, 5 Mar 2012 01:39:54 +0000 (11:39 +1000)
Change-Id: Iad2f07b989b25349fd2d4fff010e24dcd5a1688f

697 files changed:
1  2 
bin/rename-qtdeclarative-symbols.sh
doc/src/localstorage/localstorage.qdoc
doc/src/snippets/qml/viewtransitions/viewtransitions-basic.qml
doc/src/snippets/qml/viewtransitions/viewtransitions-delayedbyindex.qml
doc/src/snippets/qml/viewtransitions/viewtransitions-intermediatemove.qml
doc/src/snippets/qml/viewtransitions/viewtransitions-interruptedgood.qml
doc/src/snippets/qml/viewtransitions/viewtransitions-pathanim.qml
doc/src/snippets/qml/viewtransitions/viewtransitions-scriptactionbad.qml
doc/src/snippets/qml/viewtransitions/viewtransitions-scriptactiongood.qml
doc/src/whatsnew.qdoc
examples/HACKING
examples/demos/calculator/CalculatorCore/Button.qml
examples/demos/calculator/CalculatorCore/Display.qml
examples/demos/calculator/calculator-desktop.qml
examples/demos/calculator/calculator-mobile.qml
examples/demos/calculator/calculator.pro
examples/demos/calculator/main.cpp
examples/demos/flickr/content/Button.qml
examples/demos/flickr/content/GridDelegate.qml
examples/demos/flickr/content/ImageDetails.qml
examples/demos/flickr/content/ListDelegate.qml
examples/demos/flickr/content/Progress.qml
examples/demos/flickr/content/RssModel.qml
examples/demos/flickr/content/ScrollBar.qml
examples/demos/flickr/content/Slider.qml
examples/demos/flickr/content/TitleBar.qml
examples/demos/flickr/content/ToolBar.qml
examples/demos/flickr/content/UnifiedDelegate.qml
examples/demos/flickr/flickr-90.qml
examples/demos/flickr/flickr.qml
examples/demos/minehunt/MinehuntCore/Explosion.qml
examples/demos/minehunt/MinehuntCore/Tile.qml
examples/demos/minehunt/main.cpp
examples/demos/minehunt/minehunt.cpp
examples/demos/minehunt/minehunt.h
examples/demos/minehunt/minehunt.pro
examples/demos/minehunt/minehunt.qml
examples/demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
examples/demos/photoviewer/PhotoViewerCore/BusyIndicator.qml
examples/demos/photoviewer/PhotoViewerCore/Button.qml
examples/demos/photoviewer/PhotoViewerCore/EditableButton.qml
examples/demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml
examples/demos/photoviewer/PhotoViewerCore/ProgressBar.qml
examples/demos/photoviewer/PhotoViewerCore/RssModel.qml
examples/demos/photoviewer/PhotoViewerCore/Tag.qml
examples/demos/photoviewer/photoviewer.qml
examples/demos/plasmapatrol/content/BlasterHardpoint.qml
examples/demos/plasmapatrol/content/Button.qml
examples/demos/plasmapatrol/content/CannonHardpoint.qml
examples/demos/plasmapatrol/content/ChoiceBox.qml
examples/demos/plasmapatrol/content/Cruiser.qml
examples/demos/plasmapatrol/content/Frigate.qml
examples/demos/plasmapatrol/content/Hardpoint.qml
examples/demos/plasmapatrol/content/HelpScreens.qml
examples/demos/plasmapatrol/content/LaserHardpoint.qml
examples/demos/plasmapatrol/content/PlasmaPatrolParticles.qml
examples/demos/plasmapatrol/content/SequentialLoader.qml
examples/demos/plasmapatrol/content/Ship.qml
examples/demos/plasmapatrol/content/Sloop.qml
examples/demos/plasmapatrol/plasmapatrol.qml
examples/demos/rssnews/content/BusyIndicator.qml
examples/demos/rssnews/content/CategoryDelegate.qml
examples/demos/rssnews/content/NewsDelegate.qml
examples/demos/rssnews/content/RssFeeds.qml
examples/demos/rssnews/content/ScrollBar.qml
examples/demos/rssnews/rssnews.qml
examples/demos/samegame/content/BoomBlock.qml
examples/demos/samegame/content/Button.qml
examples/demos/samegame/content/Dialog.qml
examples/demos/samegame/content/GameArea.qml
examples/demos/samegame/content/NameInputDialog.qml
examples/demos/samegame/samegame.qml
examples/demos/snake/content/Button.qml
examples/demos/snake/content/Cookie.qml
examples/demos/snake/content/HighScoreModel.qml
examples/demos/snake/content/Link.qml
examples/demos/snake/content/Skull.qml
examples/demos/snake/snake.qml
examples/demos/twitter/TwitterCore/Button.qml
examples/demos/twitter/TwitterCore/FatDelegate.qml
examples/demos/twitter/TwitterCore/Input.qml
examples/demos/twitter/TwitterCore/Loading.qml
examples/demos/twitter/TwitterCore/MultiTitleBar.qml
examples/demos/twitter/TwitterCore/RssModel.qml
examples/demos/twitter/TwitterCore/SearchView.qml
examples/demos/twitter/TwitterCore/TitleBar.qml
examples/demos/twitter/TwitterCore/ToolBar.qml
examples/demos/twitter/TwitterCore/UserModel.qml
examples/demos/twitter/twitter.qml
examples/examples.pro
examples/qml/cppextensions/imageprovider/imageprovider.cpp
examples/qml/cppextensions/imageprovider/imageprovider.pro
examples/qml/cppextensions/plugins/plugin.cpp
examples/qml/cppextensions/plugins/plugins.pro
examples/qml/cppextensions/referenceexamples/attached/birthdayparty.cpp
examples/qml/cppextensions/referenceexamples/binding/birthdayparty.cpp
examples/qml/cppextensions/referenceexamples/coercion/birthdayparty.cpp
examples/qml/cppextensions/referenceexamples/default/birthdayparty.cpp
examples/qml/cppextensions/referenceexamples/grouped/birthdayparty.cpp
examples/qml/cppextensions/referenceexamples/methods/birthdayparty.cpp
examples/qml/cppextensions/referenceexamples/properties/birthdayparty.cpp
examples/qml/cppextensions/referenceexamples/signal/birthdayparty.cpp
examples/qml/cppextensions/referenceexamples/valuesource/birthdayparty.cpp
examples/quick/accessibility/accessibility.pro
examples/quick/accessibility/accessibility.qml
examples/quick/accessibility/accessibility.qmlproject
examples/quick/accessibility/content/Button.qml
examples/quick/accessibility/main.cpp
examples/quick/animation/animation.pro
examples/quick/animation/animation.qml
examples/quick/animation/animation.qmlproject
examples/quick/animation/basics/color-animation.qml
examples/quick/animation/basics/images/face-smile.png
examples/quick/animation/basics/images/moon.png
examples/quick/animation/basics/images/shadow.png
examples/quick/animation/basics/images/star.png
examples/quick/animation/basics/images/sun.png
examples/quick/animation/basics/property-animation.qml
examples/quick/animation/behaviors/SideRect.qml
examples/quick/animation/behaviors/behavior-example.qml
examples/quick/animation/behaviors/tvtennis.qml
examples/quick/animation/behaviors/wigglytext.qml
examples/quick/animation/easing/content/QuitButton.qml
examples/quick/animation/easing/content/quit.png
examples/quick/animation/easing/easing.qml
examples/quick/animation/main.cpp
examples/quick/animation/pathanimation/pathanimation.qml
examples/quick/animation/pathinterpolator/pathinterpolator.qml
examples/quick/animation/states/qt-logo.png
examples/quick/animation/states/states.qml
examples/quick/animation/states/transitions.qml
examples/quick/canvas/bezierCurve/bezierCurve.qml
examples/quick/canvas/clip/clip.qml
examples/quick/canvas/contents/Button.qml
examples/quick/canvas/contents/ScrollBar.qml
examples/quick/canvas/contents/Slider.qml
examples/quick/canvas/contents/Stocks.qml
examples/quick/canvas/contents/TitleBar.qml
examples/quick/canvas/contents/ToolBar.qml
examples/quick/canvas/contents/images/button-pressed.png
examples/quick/canvas/contents/images/button.png
examples/quick/canvas/contents/images/default.svg
examples/quick/canvas/contents/images/gloss.png
examples/quick/canvas/contents/images/lineedit.png
examples/quick/canvas/contents/images/lineedit.sci
examples/quick/canvas/contents/images/quit.png
examples/quick/canvas/contents/images/stripes.png
examples/quick/canvas/contents/images/titlebar.png
examples/quick/canvas/contents/images/titlebar.sci
examples/quick/canvas/contents/images/toolbutton.png
examples/quick/canvas/contents/images/toolbutton.sci
examples/quick/canvas/contents/qt-logo.png
examples/quick/canvas/quadraticCurveTo/quadraticCurveTo.qml
examples/quick/canvas/roundedrect/roundedrect.qml
examples/quick/canvas/smile/smile.qml
examples/quick/canvas/squircle/squircle.png
examples/quick/canvas/squircle/squircle.qml
examples/quick/canvas/stockchart/README
examples/quick/canvas/stockchart/com/nokia/StockChartExample/qmldir
examples/quick/canvas/stockchart/model.cpp
examples/quick/canvas/stockchart/model.h
examples/quick/canvas/stockchart/plugin.cpp
examples/quick/canvas/stockchart/stock.qml
examples/quick/canvas/stockchart/stockchart.pro
examples/quick/canvas/tiger/tiger.js
examples/quick/canvas/tiger/tiger.qml
examples/quick/canvas/twitterfriends/TwitterUser.qml
examples/quick/canvas/twitterfriends/cache.js
examples/quick/canvas/twitterfriends/twitter.qml
examples/quick/draganddrop/draganddrop.pro
examples/quick/draganddrop/draganddrop.qml
examples/quick/draganddrop/draganddrop.qmlproject
examples/quick/draganddrop/main.cpp
examples/quick/draganddrop/tiles/DragTile.qml
examples/quick/draganddrop/tiles/DropTile.qml
examples/quick/draganddrop/tiles/tiles.qml
examples/quick/draganddrop/views/gridview.qml
examples/quick/imageelements/animatedsprite.qml
examples/quick/imageelements/borderimage.qml
examples/quick/imageelements/content/BearSheet.png
examples/quick/imageelements/content/BorderImageSelector.qml
examples/quick/imageelements/content/ImageCell.qml
examples/quick/imageelements/content/MyBorderImage.qml
examples/quick/imageelements/content/ShadowRectangle.qml
examples/quick/imageelements/content/bw.png
examples/quick/imageelements/content/colors-round.sci
examples/quick/imageelements/content/colors-stretch.sci
examples/quick/imageelements/content/colors.png
examples/quick/imageelements/content/qt-logo.png
examples/quick/imageelements/content/shadow.png
examples/quick/imageelements/content/speaker.png
examples/quick/imageelements/image.qml
examples/quick/imageelements/imageelements.pro
examples/quick/imageelements/imageelements.qml
examples/quick/imageelements/imageelements.qmlproject
examples/quick/imageelements/main.cpp
examples/quick/imageelements/shadows.qml
examples/quick/imageelements/spritesequence.qml
examples/quick/keyinteraction/focus/Core/ContextMenu.qml
examples/quick/keyinteraction/focus/Core/GridMenu.qml
examples/quick/keyinteraction/focus/Core/ListMenu.qml
examples/quick/keyinteraction/focus/Core/ListViewDelegate.qml
examples/quick/keyinteraction/focus/Core/images/arrow.png
examples/quick/keyinteraction/focus/Core/images/qt-logo.png
examples/quick/keyinteraction/focus/focus.qml
examples/quick/modelviews/abstractitemmodel/abstractitemmodel.pro
examples/quick/modelviews/abstractitemmodel/abstractitemmodel.qrc
examples/quick/modelviews/abstractitemmodel/main.cpp
examples/quick/modelviews/abstractitemmodel/model.cpp
examples/quick/modelviews/abstractitemmodel/model.h
examples/quick/modelviews/abstractitemmodel/view.qml
examples/quick/modelviews/gridview/gridview-example.qml
examples/quick/modelviews/gridview/pics/AddressBook_48.png
examples/quick/modelviews/gridview/pics/AudioPlayer_48.png
examples/quick/modelviews/gridview/pics/Camera_48.png
examples/quick/modelviews/gridview/pics/DateBook_48.png
examples/quick/modelviews/gridview/pics/EMail_48.png
examples/quick/modelviews/gridview/pics/TodoList_48.png
examples/quick/modelviews/gridview/pics/VideoPlayer_48.png
examples/quick/modelviews/listview/content/PetsModel.qml
examples/quick/modelviews/listview/content/PressAndHoldButton.qml
examples/quick/modelviews/listview/content/RecipesModel.qml
examples/quick/modelviews/listview/content/TextButton.qml
examples/quick/modelviews/listview/content/ToggleButton.qml
examples/quick/modelviews/listview/content/pics/arrow-down.png
examples/quick/modelviews/listview/content/pics/arrow-up.png
examples/quick/modelviews/listview/content/pics/fruit-salad.jpg
examples/quick/modelviews/listview/content/pics/hamburger.jpg
examples/quick/modelviews/listview/content/pics/lemonade.jpg
examples/quick/modelviews/listview/content/pics/list-delete.png
examples/quick/modelviews/listview/content/pics/minus-sign.png
examples/quick/modelviews/listview/content/pics/moreDown.png
examples/quick/modelviews/listview/content/pics/moreUp.png
examples/quick/modelviews/listview/content/pics/pancakes.jpg
examples/quick/modelviews/listview/content/pics/plus-sign.png
examples/quick/modelviews/listview/content/pics/vegetable-soup.jpg
examples/quick/modelviews/listview/dynamiclist.qml
examples/quick/modelviews/listview/expandingdelegates.qml
examples/quick/modelviews/listview/highlight.qml
examples/quick/modelviews/listview/highlightranges.qml
examples/quick/modelviews/listview/sections.qml
examples/quick/modelviews/modelviews.pro
examples/quick/modelviews/modelviews.qml
examples/quick/modelviews/modelviews.qmlproject
examples/quick/modelviews/objectlistmodel/dataobject.cpp
examples/quick/modelviews/objectlistmodel/dataobject.h
examples/quick/modelviews/objectlistmodel/main.cpp
examples/quick/modelviews/objectlistmodel/objectlistmodel.pro
examples/quick/modelviews/objectlistmodel/objectlistmodel.qmlproject
examples/quick/modelviews/objectlistmodel/objectlistmodel.qrc
examples/quick/modelviews/objectlistmodel/view.qml
examples/quick/modelviews/package/Delegate.qml
examples/quick/modelviews/package/view.qml
examples/quick/modelviews/parallax/content/Clock.qml
examples/quick/modelviews/parallax/content/ParallaxView.qml
examples/quick/modelviews/parallax/content/QuitButton.qml
examples/quick/modelviews/parallax/content/Smiley.qml
examples/quick/modelviews/parallax/content/background.png
examples/quick/modelviews/parallax/content/center.png
examples/quick/modelviews/parallax/content/clock-night.png
examples/quick/modelviews/parallax/content/clock.png
examples/quick/modelviews/parallax/content/hour.png
examples/quick/modelviews/parallax/content/minute.png
examples/quick/modelviews/parallax/content/pics/background.jpg
examples/quick/modelviews/parallax/content/pics/face-smile.png
examples/quick/modelviews/parallax/content/pics/home-page.png
examples/quick/modelviews/parallax/content/pics/home-page.svg
examples/quick/modelviews/parallax/content/pics/shadow.png
examples/quick/modelviews/parallax/content/pics/yast-joystick.png
examples/quick/modelviews/parallax/content/pics/yast-wol.png
examples/quick/modelviews/parallax/content/quit.png
examples/quick/modelviews/parallax/content/second.png
examples/quick/modelviews/parallax/parallax.qml
examples/quick/modelviews/pathview/pathview-example.qml
examples/quick/modelviews/pathview/pics/AddressBook_48.png
examples/quick/modelviews/pathview/pics/AudioPlayer_48.png
examples/quick/modelviews/pathview/pics/Camera_48.png
examples/quick/modelviews/pathview/pics/DateBook_48.png
examples/quick/modelviews/pathview/pics/EMail_48.png
examples/quick/modelviews/pathview/pics/TodoList_48.png
examples/quick/modelviews/pathview/pics/VideoPlayer_48.png
examples/quick/modelviews/stringlistmodel/main.cpp
examples/quick/modelviews/stringlistmodel/stringlistmodel.pro
examples/quick/modelviews/stringlistmodel/stringlistmodel.qrc
examples/quick/modelviews/stringlistmodel/view.qml
examples/quick/modelviews/visualdatamodel/dragselection.qml
examples/quick/modelviews/visualdatamodel/slideshow.qml
examples/quick/modelviews/visualdatamodel/sortedmodel.qml
examples/quick/modelviews/visualdatamodel/visualdatamodel.qmlproject
examples/quick/modelviews/visualitemmodel/visualitemmodel.qml
examples/quick/mousearea/mousearea-example.qml
examples/quick/openglunderqml/main.cpp
examples/quick/openglunderqml/main.qml
examples/quick/openglunderqml/openglunderqml.pro
examples/quick/openglunderqml/squircle.cpp
examples/quick/openglunderqml/squircle.h
examples/quick/painteditem/painteditem.pro
examples/quick/painteditem/smile/main.cpp
examples/quick/painteditem/smile/smile.pro
examples/quick/painteditem/smile/smile.qml
examples/quick/painteditem/textballoons/TextBalloonPlugin/plugin.h
examples/quick/painteditem/textballoons/TextBalloonPlugin/qmldir
examples/quick/painteditem/textballoons/textballoon.cpp
examples/quick/painteditem/textballoons/textballoon.h
examples/quick/painteditem/textballoons/textballoon.json
examples/quick/painteditem/textballoons/textballoons.pro
examples/quick/painteditem/textballoons/textballoons.qml
examples/quick/positioners/content/Button.qml
examples/quick/positioners/content/add.png
examples/quick/positioners/content/del.png
examples/quick/positioners/positioners-attachedproperties.qml
examples/quick/positioners/positioners.qml
examples/quick/quick.pro
examples/quick/righttoleft/layoutdirection/layoutdirection.qml
examples/quick/righttoleft/layoutdirection/layoutdirection.qmlproject
examples/quick/righttoleft/layoutmirroring/layoutmirroring.qml
examples/quick/righttoleft/layoutmirroring/layoutmirroring.qmlproject
examples/quick/righttoleft/textalignment/textalignment.qml
examples/quick/righttoleft/textalignment/textalignment.qmlproject
examples/quick/shadereffects/content/Slider.qml
examples/quick/shadereffects/content/face-smile.png
examples/quick/shadereffects/content/qt-logo.png
examples/quick/shadereffects/shadereffects.qml
examples/quick/text/fonts/availableFonts.qml
examples/quick/text/fonts/banner.qml
examples/quick/text/fonts/content/fonts/tarzeau_ocr_a.ttf
examples/quick/text/fonts/fonts.qml
examples/quick/text/fonts/hello.qml
examples/quick/text/imgtag/TextWithImage.qml
examples/quick/text/imgtag/images/face-sad.png
examples/quick/text/imgtag/images/face-smile-big.png
examples/quick/text/imgtag/images/face-smile.png
examples/quick/text/imgtag/images/heart200.png
examples/quick/text/imgtag/images/qtlogo.png
examples/quick/text/imgtag/images/starfish_2.png
examples/quick/text/imgtag/imgtag.qml
examples/quick/text/styledtext-layout.qml
examples/quick/text/text.qml
examples/quick/text/text.qmlproject
examples/quick/text/textselection/pics/endHandle.png
examples/quick/text/textselection/pics/endHandle.sci
examples/quick/text/textselection/pics/startHandle.png
examples/quick/text/textselection/pics/startHandle.sci
examples/quick/text/textselection/textselection.qml
examples/quick/threading/threadedlistmodel/dataloader.js
examples/quick/threading/threadedlistmodel/threadedlistmodel.qmlproject
examples/quick/threading/threadedlistmodel/timedisplay.qml
examples/quick/threading/workerscript/workerscript.js
examples/quick/threading/workerscript/workerscript.qml
examples/quick/threading/workerscript/workerscript.qmlproject
examples/quick/touchinteraction/flickable/content/Day.qml
examples/quick/touchinteraction/flickable/content/cork.jpg
examples/quick/touchinteraction/flickable/content/note-yellow.png
examples/quick/touchinteraction/flickable/content/tack.png
examples/quick/touchinteraction/flickable/corkboards.qml
examples/quick/touchinteraction/multipointtouch/bearwhack.qml
examples/quick/touchinteraction/multipointtouch/content/AugmentedTouchPoint.qml
examples/quick/touchinteraction/multipointtouch/content/Bear0.png
examples/quick/touchinteraction/multipointtouch/content/Bear1.png
examples/quick/touchinteraction/multipointtouch/content/Bear2.png
examples/quick/touchinteraction/multipointtouch/content/Bear3.png
examples/quick/touchinteraction/multipointtouch/content/BearB.png
examples/quick/touchinteraction/multipointtouch/content/BearWhackParticleSystem.qml
examples/quick/touchinteraction/multipointtouch/content/ParticleFlame.qml
examples/quick/touchinteraction/multipointtouch/content/blur-circle.png
examples/quick/touchinteraction/multipointtouch/content/blur-circle3.png
examples/quick/touchinteraction/multipointtouch/content/heart-blur.png
examples/quick/touchinteraction/multipointtouch/content/title.png
examples/quick/touchinteraction/multipointtouch/multiflame.qml
examples/quick/touchinteraction/pincharea/flickresize.qml
examples/quick/touchinteraction/pincharea/qt-logo.jpg
examples/quick/touchinteraction/touchinteraction.qml
examples/quick/touchinteraction/touchinteraction.qmlproject
examples/tutorials/extending/chapter1-basics/chapter1-basics.pro
examples/tutorials/extending/chapter2-methods/chapter2-methods.pro
examples/tutorials/extending/chapter3-bindings/chapter3-bindings.pro
examples/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro
examples/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro
examples/tutorials/extending/chapter5-listproperties/piechart.cpp
examples/tutorials/extending/chapter5-listproperties/piechart.h
examples/tutorials/extending/chapter6-plugins/chapter6-plugins.pro
examples/tutorials/extending/chapter6-plugins/chartsplugin.cpp
examples/tutorials/extending/chapter6-plugins/chartsplugin.h
examples/tutorials/extending/chapter6-plugins/piechart.cpp
examples/tutorials/extending/chapter6-plugins/piechart.h
examples/tutorials/gettingStartedQml/filedialog/dialogPlugin.cpp
examples/tutorials/gettingStartedQml/filedialog/dialogPlugin.h
examples/window/window.cpp
examples/window/window.pro
src/imports/folderlistmodel/folderlistmodel.pro
src/imports/folderlistmodel/plugin.cpp
src/imports/folderlistmodel/qquickfolderlistmodel.cpp
src/imports/folderlistmodel/qquickfolderlistmodel.h
src/imports/localstorage/localstorage.pro
src/imports/localstorage/plugin.cpp
src/imports/testlib/main.cpp
src/imports/testlib/testlib.pro
src/imports/xmllistmodel/plugin.cpp
src/plugins/accessible/quick/main.cpp
src/plugins/accessible/quick/quick.pro
src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.cpp
src/plugins/qmltooling/qmldbg_qtquick2/qtquick2plugin.h
src/plugins/qmltooling/qmldbg_tcp/qmldbg_tcp.pro
src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
src/qml/debugger/qdebugmessageservice.cpp
src/qml/debugger/qqmldebugserverconnection_p.h
src/qml/debugger/qqmlinspectorinterface_p.h
src/qml/debugger/qqmlprofilerservice.cpp
src/qml/debugger/qqmlprofilerservice_p.h
src/qml/debugger/qv8profilerservice.cpp
src/qml/debugger/qv8profilerservice_p.h
src/qml/qml/ftw/qfastmetabuilder.cpp
src/qml/qml/qqmlboundsignal.cpp
src/qml/qml/qqmlcompiler.cpp
src/qml/qml/qqmlcompiler_p.h
src/qml/qml/qqmlcomponent.cpp
src/qml/qml/qqmlcomponent_p.h
src/qml/qml/qqmlengine.cpp
src/qml/qml/qqmlexpression.cpp
src/qml/qml/qqmlextensioninterface.h
src/qml/qml/qqmlimageprovider.h
src/qml/qml/qqmlincubator.cpp
src/qml/qml/qqmlincubator.h
src/qml/qml/qqmlinstruction.cpp
src/qml/qml/qqmllocale.cpp
src/qml/qml/qqmlpropertycache.cpp
src/qml/qml/qqmlpropertycache_p.h
src/qml/qml/qqmlpropertyvalueinterceptor_p.h
src/qml/qml/qqmlpropertyvaluesource.h
src/qml/qml/qqmlrewrite.cpp
src/qml/qml/qqmlrewrite_p.h
src/qml/qml/qqmltypeloader.cpp
src/qml/qml/qqmlvme_p.h
src/qml/qml/qquickworkerscript.cpp
src/qml/qml/v4/qv4bindings.cpp
src/qml/qml/v4/qv4bindings_p.h
src/qml/qml/v4/qv4compiler.cpp
src/qml/qml/v4/qv4compiler_p_p.h
src/qml/qml/v4/qv4instruction.cpp
src/qml/qml/v4/qv4instruction_p.h
src/qml/qml/v4/qv4ir.cpp
src/qml/qml/v4/qv4ir_p.h
src/qml/qml/v4/qv4irbuilder.cpp
src/qml/qml/v4/qv4program_p.h
src/qml/qml/v8/qjsconverter_p.h
src/qml/qml/v8/qjsengine.h
src/qml/qml/v8/qjsengine_p.h
src/qml/qml/v8/qjsvalue.h
src/qml/qml/v8/qjsvalue_impl_p.h
src/qml/qml/v8/qjsvalue_p.h
src/qml/qml/v8/qjsvalueiterator.h
src/qml/qml/v8/qjsvalueiterator_impl_p.h
src/qml/qml/v8/qjsvalueiterator_p.h
src/qml/qml/v8/qqmlbuiltinfunctions.cpp
src/qml/qml/v8/qscript_impl_p.h
src/qml/qml/v8/qscriptisolate_p.h
src/qml/qml/v8/qscriptoriginalglobalobject_p.h
src/qml/qml/v8/qscriptshareddata_p.h
src/qml/qml/v8/qscripttools_p.h
src/qml/qml/v8/qv8engine.cpp
src/qml/qml/v8/qv8engine_impl_p.h
src/qml/qml/v8/qv8engine_p.h
src/qml/qml/v8/qv8qobjectwrapper.cpp
src/quick/items/items.pri
src/quick/items/qquickanimatedsprite.cpp
src/quick/items/qquickanimatedsprite_p.h
src/quick/items/qquickcanvas.cpp
src/quick/items/qquickevents_p_p.h
src/quick/items/qquickflickable.cpp
src/quick/items/qquickgridview.cpp
src/quick/items/qquickitem.cpp
src/quick/items/qquickitem_p.h
src/quick/items/qquickitemanimation.cpp
src/quick/items/qquickitemsmodule.cpp
src/quick/items/qquickitemview.cpp
src/quick/items/qquickitemview_p.h
src/quick/items/qquickitemview_p_p.h
src/quick/items/qquickitemviewtransition.cpp
src/quick/items/qquickitemviewtransition_p.h
src/quick/items/qquicklistview.cpp
src/quick/items/qquicklistview_p.h
src/quick/items/qquickpositioners.cpp
src/quick/items/qquickpositioners_p.h
src/quick/items/qquickpositioners_p_p.h
src/quick/items/qquicksprite.cpp
src/quick/items/qquicksprite_p.h
src/quick/items/qquickspriteengine.cpp
src/quick/items/qquickspriteengine_p.h
src/quick/items/qquickspritesequence.cpp
src/quick/items/qquickspritesequence_p.h
src/quick/items/qquickstateoperations.cpp
src/quick/items/qquicktext.cpp
src/quick/items/qquicktext_p_p.h
src/quick/items/qquicktextedit.cpp
src/quick/items/qquicktextedit_p.h
src/quick/items/qquicktextedit_p_p.h
src/quick/items/qquicktextinput.cpp
src/quick/items/qquicktextinput_p.h
src/quick/items/qquicktextinput_p_p.h
src/quick/items/qquickvisualadaptormodel_p.h
src/quick/items/qquickvisualdatamodel.cpp
src/quick/items/qquickvisualdatamodel_p.h
src/quick/items/qquickvisualitemmodel_p.h
src/quick/items/qquickwindowmanager.cpp
src/quick/items/qquickwindowmanager_p.h
src/quick/items/qquickwindowmodule.cpp
src/quick/items/qquickwindowmodule_p.h
src/quick/particles/qquickage.cpp
src/quick/particles/qquickage_p.h
src/quick/particles/qquickangledirection.cpp
src/quick/particles/qquickangledirection_p.h
src/quick/particles/qquickcumulativedirection.cpp
src/quick/particles/qquickcumulativedirection_p.h
src/quick/particles/qquickcustomaffector.cpp
src/quick/particles/qquickcustomaffector_p.h
src/quick/particles/qquickdirection.cpp
src/quick/particles/qquickdirection_p.h
src/quick/particles/qquickellipseextruder.cpp
src/quick/particles/qquickellipseextruder_p.h
src/quick/particles/qquickfriction.cpp
src/quick/particles/qquickfriction_p.h
src/quick/particles/qquickgravity.cpp
src/quick/particles/qquickgravity_p.h
src/quick/particles/qquickgroupgoal.cpp
src/quick/particles/qquickgroupgoal_p.h
src/quick/particles/qquickimageparticle.cpp
src/quick/particles/qquickimageparticle_p.h
src/quick/particles/qquickitemparticle.cpp
src/quick/particles/qquickitemparticle_p.h
src/quick/particles/qquicklineextruder.cpp
src/quick/particles/qquicklineextruder_p.h
src/quick/particles/qquickmaskextruder.cpp
src/quick/particles/qquickmaskextruder_p.h
src/quick/particles/qquickparticleaffector.cpp
src/quick/particles/qquickparticleaffector_p.h
src/quick/particles/qquickparticleemitter.cpp
src/quick/particles/qquickparticleemitter_p.h
src/quick/particles/qquickparticleextruder.cpp
src/quick/particles/qquickparticleextruder_p.h
src/quick/particles/qquickparticlegroup.cpp
src/quick/particles/qquickparticlegroup_p.h
src/quick/particles/qquickparticlepainter.cpp
src/quick/particles/qquickparticlepainter_p.h
src/quick/particles/qquickparticlesmodule.cpp
src/quick/particles/qquickparticlesmodule_p.h
src/quick/particles/qquickparticlesystem.cpp
src/quick/particles/qquickparticlesystem_p.h
src/quick/particles/qquickpointattractor.cpp
src/quick/particles/qquickpointattractor_p.h
src/quick/particles/qquickpointdirection.cpp
src/quick/particles/qquickpointdirection_p.h
src/quick/particles/qquickrectangleextruder.cpp
src/quick/particles/qquickrectangleextruder_p.h
src/quick/particles/qquickspritegoal.cpp
src/quick/particles/qquickspritegoal_p.h
src/quick/particles/qquicktargetdirection.cpp
src/quick/particles/qquicktargetdirection_p.h
src/quick/particles/qquicktrailemitter.cpp
src/quick/particles/qquicktrailemitter_p.h
src/quick/particles/qquickturbulence.cpp
src/quick/particles/qquickturbulence_p.h
src/quick/particles/qquickv8particledata.cpp
src/quick/particles/qquickv8particledata_p.h
src/quick/particles/qquickwander.cpp
src/quick/particles/qquickwander_p.h
src/quick/scenegraph/coreapi/qsgnode.cpp
src/quick/scenegraph/coreapi/qsgrendernode.cpp
src/quick/scenegraph/coreapi/qsgrendernode_p.h
src/quick/scenegraph/qsgadaptationlayer.cpp
src/quick/scenegraph/qsgcontext.cpp
src/quick/scenegraph/qsgcontextplugin.cpp
src/quick/scenegraph/qsgcontextplugin_p.h
src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
src/quick/scenegraph/qsgdefaultrectanglenode.cpp
src/quick/scenegraph/qsgdefaultrectanglenode_p.h
src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
src/quick/scenegraph/util/qsgdistancefieldutil.cpp
src/quick/scenegraph/util/qsgdistancefieldutil_p.h
src/quick/scenegraph/util/qsgtexture.cpp
src/quick/util/qquickanimationcontroller_p.h
src/quick/util/qquickpixmapcache.cpp
src/quick/util/qquickstyledtext.cpp
src/quick/util/qquickstyledtext_p.h
tests/auto/host.pro
tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro
tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
tests/auto/qml/qml.pro
tests/auto/qml/qmlmin/tst_qmlmin.cpp
tests/auto/qml/qqmlcomponent/data/createParentReference.qml
tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
tests/auto/qml/qqmlecmascript/data/jsimport/importModuleApi.js
tests/auto/qml/qqmlecmascript/data/jsimport/testImportModuleApi.qml
tests/auto/qml/qqmlecmascript/data/rewriteMultiLineStrings_crlf.1.qml
tests/auto/qml/qqmlecmascript/data/signalAssignment.3.qml
tests/auto/qml/qqmlecmascript/data/signalAssignment.4.qml
tests/auto/qml/qqmlecmascript/testtypes.h
tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
tests/auto/qml/qqmlinstruction/tst_qqmlinstruction.cpp
tests/auto/qml/qqmllanguage/data/signal.5.errors.txt
tests/auto/qml/qqmllanguage/data/signal.5.qml
tests/auto/qml/qqmllanguage/testtypes.h
tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
tests/auto/qml/qqmlmetaobject/data/method.1.qml
tests/auto/qml/qqmlmetaobject/data/method.2.qml
tests/auto/qml/qqmlmetaobject/data/method.3.qml
tests/auto/qml/qqmlmetaobject/data/property.MyQmlObject.qml
tests/auto/qml/qqmlmetaobject/data/property.QtObject.qml
tests/auto/qml/qqmlmetaobject/data/property.alias.2.qml
tests/auto/qml/qqmlmetaobject/data/property.alias.3.qml
tests/auto/qml/qqmlmetaobject/data/property.alias.qml
tests/auto/qml/qqmlmetaobject/data/property.bool.qml
tests/auto/qml/qqmlmetaobject/data/property.color.qml
tests/auto/qml/qqmlmetaobject/data/property.date.qml
tests/auto/qml/qqmlmetaobject/data/property.int.qml
tests/auto/qml/qqmlmetaobject/data/property.list.MyQmlObject.qml
tests/auto/qml/qqmlmetaobject/data/property.list.QtObject.qml
tests/auto/qml/qqmlmetaobject/data/property.real.qml
tests/auto/qml/qqmlmetaobject/data/property.string.qml
tests/auto/qml/qqmlmetaobject/data/property.url.qml
tests/auto/qml/qqmlmetaobject/data/property.var.qml
tests/auto/qml/qqmlmetaobject/data/property.variant.qml
tests/auto/qml/qqmlmetaobject/data/signal.1.qml
tests/auto/qml/qqmlmetaobject/data/signal.2.qml
tests/auto/qml/qqmlmetaobject/data/signal.3.qml
tests/auto/qml/qqmlmetaobject/data/signal.4.qml
tests/auto/qml/qqmlmetaobject/data/signal.5.qml
tests/auto/qml/qqmlmetaobject/qqmlmetaobject.pro
tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
tests/auto/qml/qqmlmoduleplugin/empty.json
tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp
tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp
tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp
tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp
tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp
tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp
tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp
tests/auto/qml/qqmlvaluetypes/data/nonValueTypeComparison.qml
tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
tests/auto/qml/v4/data/colorType.qml
tests/auto/qml/v4/tst_v4.cpp
tests/auto/quick/examples/tst_examples.cpp
tests/auto/quick/qquickanchors/data/stretch.qml
tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
tests/auto/quick/qquickanimatedsprite/data/basic.qml
tests/auto/quick/qquickanimatedsprite/data/squarefacesprite.png
tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro
tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
tests/auto/quick/qquickdroparea/qquickdroparea.pro
tests/auto/quick/qquickdroparea/tst_qquickdroparea.cpp
tests/auto/quick/qquickgridview/data/displacedTransitions.qml
tests/auto/quick/qquickgridview/data/multipleTransitions.qml
tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
tests/auto/quick/qquicklistview/data/displacedTransitions.qml
tests/auto/quick/qquicklistview/data/multipleTransitions.qml
tests/auto/quick/qquicklistview/data/sectionpropertychange.qml
tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
tests/auto/quick/qquickpositioners/data/transitions.qml
tests/auto/quick/qquickpositioners/qquickpositioners.pro
tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
tests/auto/quick/qquickspritesequence/data/advance.qml
tests/auto/quick/qquickspritesequence/data/basic.qml
tests/auto/quick/qquickspritesequence/data/squarefacesprite.png
tests/auto/quick/qquickspritesequence/qquickspritesequence.pro
tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp
tests/auto/quick/qquicktext/data/fontSizeMode.qml
tests/auto/quick/qquicktext/data/multilengthStrings.qml
tests/auto/quick/qquicktext/data/multilengthStringsWrapped.qml
tests/auto/quick/qquicktext/data/multilineelide.qml
tests/auto/quick/qquicktext/data/pixelFontSizes.qml
tests/auto/quick/qquicktext/data/pointFontSizes.qml
tests/auto/quick/qquicktext/tst_qquicktext.cpp
tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
tests/auto/quick/quick.pro
tests/auto/quick/shared/viewtestutil.h
tests/benchmarks/qml/script/data/enums.qml
tests/benchmarks/qml/script/data/namespacedEnums.qml
tests/benchmarks/qml/script/data/scriptCall.qml
tests/benchmarks/qml/script/data/signal_heavyArgsAccess.qml
tests/benchmarks/qml/script/data/signal_heavyIdAccess.qml
tests/benchmarks/qml/script/script.pro
tests/benchmarks/qml/script/tst_script.cpp
tools/qmlplugindump/main.cpp
tools/qmlprofiler/profileclient.cpp
tools/qmlprofiler/profileclient.h
tools/qmlprofiler/profiledata.cpp
tools/qmlprofiler/profiledata.h
tools/qmlprofiler/qmlprofilerapplication.cpp
tools/qmlprofiler/qmlprofilerapplication.h

index 8418502,0000000..0d521dd
mode 100755,000000..100755
--- /dev/null
@@@ -1,639 -1,0 +1,642 @@@
 +#!/bin/sh
 +#############################################################################
 +##
 +## Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +## Contact: http://www.qt-project.org/
 +##
 +## This file is part of the QtQml module of the Qt Toolkit.
 +##
 +## $QT_BEGIN_LICENSE:LGPL$
 +## GNU Lesser General Public License Usage
 +## This file may be used under the terms of the GNU Lesser General Public
 +## License version 2.1 as published by the Free Software Foundation and
 +## appearing in the file LICENSE.LGPL included in the packaging of this
 +## file. Please review the following information to ensure the GNU Lesser
 +## General Public License version 2.1 requirements will be met:
 +## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +##
 +## In addition, as a special exception, Nokia gives you certain additional
 +## rights. These rights are described in the Nokia Qt LGPL Exception
 +## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +##
 +## GNU General Public License Usage
 +## Alternatively, this file may be used under the terms of the GNU General
 +## Public License version 3.0 as published by the Free Software Foundation
 +## and appearing in the file LICENSE.GPL included in the packaging of this
 +## file. Please review the following information to ensure the GNU General
 +## Public License version 3.0 requirements will be met:
 +## http://www.gnu.org/copyleft/gpl.html.
 +##
 +## Other Usage
 +## Alternatively, this file may be used in accordance with the terms and
 +## conditions contained in a signed written agreement between you and Nokia.
 +##
 +##
 +##
 +##
 +##
 +##
 +## $QT_END_LICENSE$
 +##
 +#############################################################################
 +
 +# Replaces deprecated QDeclarative symbol names with their replacements
 +#
 +# Changes instances in all regular files under the specified directory;
 +# use on a clean source tree!
 +
 +if [ "$#" -lt "1" ]
 +then
 +    echo "    Usage: $0 <directory>"
 +    exit 1;
 +fi
 +
 +MODIFY_DIR="$1"
 +
 +QML_SYMBOLS="\
 +    QDeclarativeAbstractBinding
 +    QDeclarativeAbstractBoundSignal
 +    QDeclarativeAbstractExpression
 +    QDeclarativeAccessible
 +    QDeclarativeAccessors
 +    QDeclarativeAccessorProperties
 +    QDeclarativeAnimationTimer
 +    QDeclarativeAssociationList
 +    QDeclarativeAttachedPropertiesFunc
 +    QDeclarativeBinding
 +    QDeclarativeBindingPrivate
 +    QDeclarativeBindingProfiler
 +    QDeclarativeBoundSignal
 +    QDeclarativeBoundSignalParameters
 +    QDeclarativeBoundSignalProxy
 +    QDeclarativeBuiltinFunctions
 +    QDeclarativeCleanup
 +    QDeclarativeColorValueType
 +    QDeclarativeCompiledData
 +    QDeclarativeCompiler
 +    QDeclarativeCompilerTypes
++    QDeclarativeCompilingProfiler
 +    QDeclarativeComponent
 +    QDeclarativeComponentAttached
 +    QDeclarativeComponentExtension
 +    QDeclarativeComponentPrivate
 +    QDeclarativeComponent_setQmlParent
 +    QDeclarativeCompositeTypeData
 +    QDeclarativeConnectionsParser
 +    QDeclarativeContext
 +    QDeclarativeContextData
 +    QDeclarativeContextPrivate
 +    QDeclarativeCustomParser
 +    QDeclarativeCustomParserNode
 +    QDeclarativeCustomParserNodePrivate
 +    QDeclarativeCustomParserProperty
 +    QDeclarativeCustomParserPropertyPrivate
 +    QDeclarativeData
 +    QDeclarativeDataBlob
 +    QDeclarativeDataExtended
 +    QDeclarativeDataLoader
 +    QDeclarativeDataLoaderNetworkReplyProxy
 +    QDeclarativeDataLoaderThread
 +    QDeclarativeDateExtension
 +    QDeclarativeDataTest
 +    QDeclarativeDebug
 +    QDeclarativeDebugClient
 +    QDeclarativeDebugClientPrivate
 +    QDeclarativeDebugConnection
 +    QDeclarativeDebugConnectionPrivate
 +    QDeclarativeDebugContextReference
 +    QDeclarativeDebugData
 +    QDeclarativeDebugEngineReference
 +    QDeclarativeDebugEnginesQuery
 +    QDeclarativeDebugExpressionQuery
 +    QDeclarativeDebugFileReference
 +    QDeclarativeDebugger
 +    QDeclarativeDebuggingEnabler
 +    QDeclarativeDebugHelper
 +    QDeclarativeDebugObjectExpressionWatch
 +    QDeclarativeDebugObjectQuery
 +    QDeclarativeDebugObjectReference
 +    QDeclarativeDebugPropertyReference
 +    QDeclarativeDebugPropertyWatch
 +    QDeclarativeDebugQuery
 +    QDeclarativeDebugRootContextQuery
 +    QDeclarativeDebugServer
 +    QDeclarativeDebugServerConnection
 +    QDeclarativeDebugServerPrivate
 +    QDeclarativeDebugServerThread
 +    QDeclarativeDebugService
 +    QDeclarativeDebugServicePrivate
 +    QDeclarativeDebugStatesDelegate
 +    QDeclarativeDebugTrace
 +    QDeclarativeDebugWatch
 +    QDeclarativeDelayedError
 +    QDeclarativeDirComponents
 +    QDeclarativeDirParser
 +    QDeclarativeDirScripts
 +    QDeclarativeDOMNodeResource
 +    QDeclarativeEasingValueType
 +    QDeclarativeElement
 +    QDeclarativeEngine
 +    QDeclarativeEngineDebug
 +    QDeclarativeEngineDebugClient
 +    QDeclarativeEngineDebugService
 +    QDeclarativeEngineDebugPrivate
 +    QDeclarativeEnginePrivate
 +    QDeclarativeError
 +    QDeclarativeErrorPrivate
 +    QDeclarativeExpression
 +    QDeclarativeExpressionPrivate
 +    QDeclarativeExtensionInterface
 +    QDeclarativeExtensionPlugin
 +    QDeclarativeFontValueType
 +    QDeclarativeGraphics_DerivedObject
 +    QDeclarativeGuard
 +    QDeclarativeGuardedContextData
 +    QDeclarativeGuardImpl
++    QDeclarativeHandlingSignalProfiler
 +    QDeclarativeImageProvider
 +    QDeclarativeImageProviderPrivate
 +    QDeclarativeImportDatabase
 +    QDeclarativeImportedNamespace
 +    QDeclarativeImports
 +    QDeclarativeImportsPrivate
 +    QDeclarativeIncubationController
 +    QDeclarativeIncubator
 +    QDeclarativeIncubatorController
 +    QDeclarativeIncubatorPrivate
 +    QDeclarativeIncubators
 +    QDeclarativeInfo
 +    QDeclarativeInfoPrivate
 +    QDeclarativeInspector
 +    QDeclarativeInspectorInterface
 +    QDeclarativeInspectorService
 +    QDeclarativeInstruction
 +    QDeclarativeInstructionData
 +    QDeclarativeInstructionMeta
 +    QDeclarativeIntegerCache
 +    QDeclarativeJavaScriptExpression
 +    QDeclarativeJavaScriptExpressionGuard
 +    QDeclarativeJS
 +    QDeclarativeJSGrammar
 +    QDeclarativeListProperty
 +    QDeclarativeListReference
 +    QDeclarativeListReferencePrivate
 +    QDeclarativeLocale
 +    QDeclarativeLocalStoragePlugin
 +    QDeclarativeMatrix4x4ValueType
 +    QDeclarativeMetaType
 +    QDeclarativeMetaTypeData
 +    QDeclarativeNetworkAccessManagerFactory
 +    QDeclarativeNotifier
 +    QDeclarativeNotifierEndpoint
 +    QDeclarativeNullableValue
 +    QDeclarativeNumberExtension
++    QDeclarativeObjectCreatingProfiler
 +    QDeclarativeObjectData
 +    QDeclarativeObjectProperty
 +    QDeclarativeObserverMode
 +    QDeclarativeOpenMetaObject
 +    QDeclarativeOpenMetaObjectPrivate
 +    QDeclarativeOpenMetaObjectType
 +    QDeclarativeOpenMetaObjectTypePrivate
 +    QDeclarativeParser
 +    QDeclarativeParserStatus
 +    QDeclarativePointFValueType
 +    QDeclarativePointValueType
 +    QDeclarativePool
 +    QDeclarativePrivate
 +    QDeclarativeProfilerData
 +    QDeclarativeProfilerService
 +    QDeclarativeProperties
 +    QDeclarativeProperty
 +    QDeclarativePropertyCache
 +    QDeclarativePropertyCacheMethodArguments
 +    QDeclarativePropertyData
 +    QDeclarativePropertyMap
 +    QDeclarativePropertyMapMetaObject
 +    QDeclarativePropertyMapPrivate
 +    QDeclarativePropertyPrivate
 +    QDeclarativePropertyRawData
 +    QDeclarativePropertyValueInterceptor
 +    QDeclarativePropertyValueSource
 +    QDeclarativeProxyMetaObject
 +    QDeclarativeQmldirData
 +    QDeclarativeQtQuick1Module
 +    QDeclarativeQtQuick2Module
 +    QDeclarativeQtQuick2DebugStatesDelegate
 +    QDeclarativeQuaternionValueType
 +    QDeclarativeRectFValueType
 +    QDeclarativeRectValueType
 +    QDeclarativeRefCount
 +    QDeclarativeRefPointer
 +    QDeclarativeRegisterType
 +    QDeclarativeRewrite
 +    QDeclarativeScript
 +    QDeclarativeScriptBlob
 +    QDeclarativeScriptData
 +    QDeclarativeScriptPrivate
 +    QDeclarativeScriptString
 +    QDeclarativeScriptStringPrivate
 +    QDeclarativeSizeFValueType
 +    QDeclarativeSizeValueType
 +    QDeclarativeSqlDatabaseData
 +    QDeclarativeStringConverters
 +    QDeclarativeThread
 +    QDeclarativeThreadPrivate
 +    QDeclarativeTrace
 +    QDeclarativeType
 +    QDeclarativeTypeData
 +    QDeclarativeTypeInfo
 +    QDeclarativeTypeLoader
 +    QDeclarativeTypeModule
 +    QDeclarativeTypeModulePrivate
 +    QDeclarativeTypeModuleVersion
 +    QDeclarativeTypeNameCache
 +    QDeclarativeTypeNotAvailable
 +    QDeclarativeTypePrivate
 +    QDeclarativeTypesExtensionInterface
 +    QDeclarativeV8Function
 +    QDeclarativeV8Handle
 +    QDeclarativeValueType
 +    QDeclarativeValueTypeProxyBinding
 +    QDeclarativeValueTypeFactory
 +    QDeclarativeVector2DValueType
 +    QDeclarativeVector3DValueType
 +    QDeclarativeVector4DValueType
 +    QDeclarativeVME
 +    QDeclarativeVMEGuard
 +    QDeclarativeVMEMetaData
 +    QDeclarativeVMEMetaObject
 +    QDeclarativeVMEMetaObjectEndpoint
 +    QDeclarativeVMEVariant
 +    QDeclarativeVMETypes
 +    QDeclarativeWatcher
 +    QDeclarativeWatchProxy
 +    QDeclarativeXMLHttpRequest
 +    QDeclarativeXMLHttpRequestData
 +    QDeclarative_isFileCaseCorrect
 +    QDeclarative_setParent_noEvent
 +    QQuickProperties
 +    QQuickPropertyCacheMethodArguments
 +    QQuickPropertyData
 +"
 +
 +QUICK_SYMBOLS="\
 +    QDeclarativeAbstractAnimation
 +    QDeclarativeAbstractAnimationAction
 +    QDeclarativeAbstractAnimationPrivate
 +    QDeclarativeAction
 +    QDeclarativeActionEvent
 +    QDeclarativeAnchors
 +    QDeclarativeAnimationController
 +    QDeclarativeAnimationControllerPrivate
 +    QDeclarativeAnimationGroup
 +    QDeclarativeAnimationGroupPrivate
 +    QDeclarativeAnimationPropertyUpdater
 +    QDeclarativeApplication
 +    QDeclarativeApplicationPrivate
 +    QDeclarativeBehavior
 +    QDeclarativeBehaviorPrivate
 +    QDeclarativeBind
 +    QDeclarativeBindPrivate
 +    QDeclarativeBulkValueAnimator
 +    QDeclarativeBulkValueUpdater
 +    QDeclarativeCachedBezier
 +    QDeclarativeChangeSet
 +    QDeclarativeColorAnimation
 +    QDeclarativeConnections
 +    QDeclarativeConnectionsPrivate
 +    QDeclarativeCurve
 +    QDeclarativeDefaultTextureFactory
 +    QDeclarativeFlick
 +    QDeclarativeFocusPanel
 +    QDeclarativeFolderListModel
 +    QDeclarativeFolderListModelPrivate
 +    QDeclarativeFontLoader
 +    QDeclarativeFontLoaderPrivate
 +    QDeclarativeFontObject
 +    QDeclarativeGestureArea
 +    QDeclarativeGestureAreaParser
 +    QDeclarativeGestureAreaPrivate
 +    QDeclarativeGraphics
 +    QDeclarativeItem
 +    QDeclarativeItemAccessor
 +    QDeclarativeItemChangeListener
 +    QDeclarativeItemKeyFilter
 +    QDeclarativeItemPrivate
 +    QDeclarativeListAccessor
 +    QDeclarativeListCompositor
 +    QDeclarativeListElement
 +    QDeclarativeListModel
 +    QDeclarativeListModelParser
 +    QDeclarativeListModelWorkerAgent
 +    QDeclarativeListView
 +    QDeclarativeNumberAnimation
 +    QDeclarativePackage
 +    QDeclarativePackageAttached
 +    QDeclarativePackagePrivate
 +    QDeclarativeParallelAnimation
 +    QDeclarativeParticle
 +    QDeclarativeParticleMotion
 +    QDeclarativeParticleMotionGravity
 +    QDeclarativeParticleMotionLinear
 +    QDeclarativeParticleMotionWander
 +    QDeclarativeParticles
 +    QDeclarativeParticlesPainter
 +    QDeclarativeParticlesPrivate
 +    QDeclarativePath
 +    QDeclarativePathArc
 +    QDeclarativePathAttribute
 +    QDeclarativePathCatmullRomCurve
 +    QDeclarativePathCubic
 +    QDeclarativePathCurve
 +    QDeclarativePathData
 +    QDeclarativePathElement
 +    QDeclarativePathInterpolator
 +    QDeclarativePathLine
 +    QDeclarativePathPercent
 +    QDeclarativePathPrivate
 +    QDeclarativePathQuad
 +    QDeclarativePathSvg
 +    QDeclarativePauseAnimation
 +    QDeclarativePauseAnimationPrivate
 +    QDeclarativePixmap
 +    QDeclarativePixmapData
 +    QDeclarativePixmapKey
 +    QDeclarativePixmapNull
 +    QDeclarativePixmapReader
 +    QDeclarativePixmapReaderThreadObject
 +    QDeclarativePixmapReply
 +    QDeclarativePixmapStore
 +    QDeclarativePropertyAction
 +    QDeclarativePropertyActionPrivate
 +    QDeclarativePropertyAnimation
 +    QDeclarativePropertyAnimationPrivate
 +    QDeclarativePropertyChanges
 +    QDeclarativePropertyChangesParser
 +    QDeclarativePropertyChangesPrivate
 +    QDeclarativeReplaceSignalHandler
 +    QDeclarativeRevertAction
 +    QDeclarativeRotationAnimation
 +    QDeclarativeRotationAnimationPrivate
 +    QDeclarativeSequentialAnimation
 +    QDeclarativeScriptAction
 +    QDeclarativeScriptActionPrivate
 +    QDeclarativeSetPropertyAnimationAction
 +    QDeclarativeSimpleAction
 +    QDeclarativeSmoothedAnimation
 +    QDeclarativeSmoothedAnimationPrivate
 +    QDeclarativeSpringAnimation
 +    QDeclarativeSpringAnimationPrivate
 +    QDeclarativeState
 +    QDeclarativeStateActions
 +    QDeclarativeStateChange
 +    QDeclarativeStateChangeScript
 +    QDeclarativeStateChangeScriptPrivate
 +    QDeclarativeStateGroup
 +    QDeclarativeStateGroupPrivate
 +    QDeclarativeStateOperation
 +    QDeclarativeStateOperationPrivate
 +    QDeclarativeStatePrivate
 +    QDeclarativeStyledText
 +    QDeclarativeStyledTextImgTag
 +    QDeclarativeStyledTextPrivate
 +    QDeclarativeSystemPalette
 +    QDeclarativeSystemPalettePrivate
 +    QDeclarativeTextureFactory
 +    QDeclarativeTimeLine
 +    QDeclarativeTimeLineCallback
 +    QDeclarativeTimeLineObject
 +    QDeclarativeTimeLinePrivate
 +    QDeclarativeTimeLineValue
 +    QDeclarativeTimeLineValueProxy
 +    QDeclarativeTimeLineValues
 +    QDeclarativeTimer
 +    QDeclarativeTimerPrivate
 +    QDeclarativeTransition
 +    QDeclarativeTransitionInstance
 +    QDeclarativeTransitionManager
 +    QDeclarativeTransitionManagerPrivate
 +    QDeclarativeTransitionPrivate
 +    QDeclarativeUtilModule
 +    QDeclarativeVector3dAnimation
 +    QDeclarativeView
 +    QDeclarativeViewInspector
 +    QDeclarativeViewInspectorPrivate
 +    QDeclarativeViewPrivate
 +    QDeclarativeWebView
 +    QDeclarativeXmlListModel
 +    QDeclarativeXmlListModelPrivate
 +    QDeclarativeXmlListModelRole
 +    QDeclarativeXmlListRange
 +    QDeclarativeXmlQueryEngine
 +    QDeclarativeXmlQueryResult
 +    QDeclarativeXmlQueryThreadObject
 +    QDeclarativeXmlRoleList
 +    QDeclarativeSvgParser
 +    QDeclarativeWorkerScript
 +    QDeclarativeWorkerScriptEngine
 +    QDeclarativeWorkerScriptEnginePrivate
 +"
 +
 +QML_INCLUDE_FILES="\
 +    qdeclarativeaccessible.h
 +    qdeclarativeaccessors_p.h
 +    qdeclarativebinding_p.h
 +    qdeclarativebinding_p_p.h
 +    qdeclarativeboundsignal_p.h
 +    qdeclarativebuiltinfunctions_p.h
 +    qdeclarativecleanup_p.h
 +    qdeclarativecompiler_p.h
 +    qdeclarativecomponentattached_p.h
 +    qdeclarativecomponent.h
 +    qdeclarativecomponent_p.h
 +    qdeclarativecontext.h
 +    qdeclarativecontext_p.h
 +    qdeclarativecustomparser_p.h
 +    qdeclarativecustomparser_p_p.h
 +    qdeclarativedata_p.h
 +    qdeclarativedebugclient_p.h
 +    qdeclarativedebug.h
 +    qdeclarativedebughelper_p.h
 +    qdeclarativedebugserverconnection_p.h
 +    qdeclarativedebugserver_p.h
 +    qdeclarativedebugservice_p.h
 +    qdeclarativedebugservice_p_p.h
 +    qdeclarativedebugstatesdelegate_p.h
 +    qdeclarativedebugtrace_p.h
 +    qdeclarativedirparser_p.h
 +    qdeclarativeenginedebug_p.h
 +    qdeclarativeenginedebugservice_p.h
 +    qdeclarativeengine.h
 +    qdeclarativeengine_p.h
 +    qdeclarativeerror.h
 +    qdeclarativeexpression.h
 +    qdeclarativeexpression_p.h
 +    qdeclarativeextensioninterface.h
 +    qdeclarativeextensionplugin.h
 +    qdeclarativeglobal_p.h
 +    qdeclarativeguard_p.h
 +    qdeclarative.h
 +    qdeclarativeimageprovider.h
 +    qdeclarativeimport_p.h
 +    qdeclarativeincubator.h
 +    qdeclarativeincubator_p.h
 +    qdeclarativeinfo.h
 +    qdeclarativeinspectorinterface_p.h
 +    qdeclarativeinspectorprotocol.h
 +    qdeclarativeinspectorservice_p.h
 +    qdeclarativeinstruction_p.h
 +    qdeclarativeintegercache_p.h
 +    qdeclarativejsastfwd_p.h
 +    qdeclarativejsast_p.h
 +    qdeclarativejsastvisitor_p.h
 +    qdeclarativejsengine_p.h
 +    qdeclarativejsglobal_p.h
 +    qdeclarativejsgrammar_p.h
 +    qdeclarativejskeywords_p.h
 +    qdeclarativejslexer_p.h
 +    qdeclarativejsmemorypool_p.h
 +    qdeclarativejsparser_p.h
 +    qdeclarativelist.h
 +    qdeclarativelist_p.h
 +    qdeclarativelocale_p.h
 +    qdeclarativemetatype_p.h
 +    qdeclarativenetworkaccessmanagerfactory.h
 +    qdeclarativenotifier_p.h
 +    qdeclarativenullablevalue_p_p.h
 +    qdeclarativeopenmetaobject_p.h
 +    qdeclarativeparserstatus.h
 +    qdeclarativepool_p.h
 +    qdeclarativeprivate.h
 +    qdeclarativeprofilerservice_p.h
 +    qdeclarativepropertycache_p.h
 +    qdeclarativeproperty.h
 +    qdeclarativepropertymap.h
 +    qdeclarativeproperty_p.h
 +    qdeclarativepropertyvalueinterceptor_p.h
 +    qdeclarativepropertyvaluesource.h
 +    qdeclarativeproxymetaobject_p.h
 +    qdeclarativerefcount_p.h
 +    qdeclarativerewrite_p.h
 +    qdeclarativescript_p.h
 +    qdeclarativescriptstring.h
 +    qdeclarativescriptstring_p.h
 +    qdeclarativesqldatabase_p.h
 +    qdeclarativestringconverters_p.h
 +    qdeclarativethread_p.h
 +    qdeclarativetrace_p.h
 +    qdeclarativetypeloader_p.h
 +    qdeclarativetypenamecache_p.h
 +    qdeclarativetypenotavailable_p.h
 +    qdeclarativevaluetype_p.h
 +    qdeclarativevmemetaobject_p.h
 +    qdeclarativevme_p.h
 +    qdeclarativewatcher_p.h
 +    qdeclarativexmlhttprequest_p.h
 +    qdeclarativexmllistmodel_p.h
 +"
 +
 +QUICK_INCLUDE_FILES="\
 +    qdeclarativeanimation_p.h
 +    qdeclarativeanimation_p_p.h
 +    qdeclarativeanimationcontroller_p.h
 +    qdeclarativeapplication_p.h
 +    qdeclarativebehavior_p.h
 +    qdeclarativebind_p.h
 +    qdeclarativechangeset_p.h
 +    qdeclarativeconnections_p.h
 +    qdeclarativefolderlistmodel.h
 +    qdeclarativefontloader_p.h
 +    qdeclarativelistaccessor_p.h
 +    qdeclarativelistcompositor_p.h
 +    qdeclarativelistmodel_p.h
 +    qdeclarativelistmodel_p_p.h
 +    qdeclarativelistmodelworkeragent_p.h
 +    qdeclarativepackage_p.h
 +    qdeclarativepathinterpolator_p.h
 +    qdeclarativepath_p.h
 +    qdeclarativepath_p_p.h
 +    qdeclarativepixmapcache_p.h
 +    qdeclarativepropertychanges_p.h
 +    qdeclarativesmoothedanimation_p.h
 +    qdeclarativesmoothedanimation_p_p.h
 +    qdeclarativespringanimation_p.h
 +    qdeclarativestategroup_p.h
 +    qdeclarativestateoperations_p.h
 +    qdeclarativestate_p.h
 +    qdeclarativestate_p_p.h
 +    qdeclarativestyledtext_p.h
 +    qdeclarativesvgparser_p.h
 +    qdeclarativesystempalette_p.h
 +    qdeclarativetimeline_p_p.h
 +    qdeclarativetimer_p.h
 +    qdeclarativetransitionmanager_p_p.h
 +    qdeclarativetransition_p.h
 +    qdeclarativeutilmodule_p.h
 +    qdeclarativeworkerscript_p.h
 +"
 +
 +replaceMatch()
 +{
 +    SYMBOL="$1"
 +    REPLACEMENT="$2"
 +    echo "Replacing $SYMBOL with $REPLACEMENT:"
 +
 +    CONTAINERS=$(find "$MODIFY_DIR" ! -path ".git" -type f | xargs grep -l -I "$SYMBOL")
 +    for CONTAINER in $CONTAINERS
 +    do
 +        echo "    $CONTAINER"
 +        TMP_FILE="$CONTAINER.tmp"
 +
 +        sed 's|'"$SYMBOL"'|'"$REPLACEMENT"'|g' <"$CONTAINER" >"$TMP_FILE"
 +        mv "$TMP_FILE" "$CONTAINER"
 +    done
 +    echo
 +}
 +
 +for QML_SYMBOL in $QML_SYMBOLS
 +do
 +    QML_REPLACEMENT="QQml${QML_SYMBOL#QDeclarative}"
 +    replaceMatch "\<QtDeclarative/$QML_SYMBOL\>" "QtQml/$QML_REPLACEMENT"
 +    replaceMatch "\<$QML_SYMBOL\>" "$QML_REPLACEMENT"
 +done
 +
 +for QUICK_SYMBOL in $QUICK_SYMBOLS
 +do
 +    QUICK_REPLACEMENT="QQuick${QUICK_SYMBOL#QDeclarative}"
 +    replaceMatch "\<QtDeclarative/$QUICK_SYMBOL\>" "QtQuick/$QUICK_REPLACEMENT"
 +    replaceMatch "\<$QUICK_SYMBOL\>" "$QUICK_REPLACEMENT"
 +done
 +
 +for QML_INCLUDE_FILE in $QML_INCLUDE_FILES
 +do
 +    QML_INCLUDE_REPLACEMENT="qqml${QML_INCLUDE_FILE#qdeclarative}"
 +    replaceMatch "\<$QML_INCLUDE_FILE\>" "$QML_INCLUDE_REPLACEMENT"
 +done
 +
 +for QUICK_INCLUDE_FILE in $QUICK_INCLUDE_FILES
 +do
 +    QUICK_INCLUDE_REPLACEMENT="qquick${QUICK_INCLUDE_FILE#qdeclarative}"
 +    replaceMatch "\<$QUICK_INCLUDE_FILE\>" "$QUICK_INCLUDE_REPLACEMENT"
 +done
 +
 +# Various one-off replacements
 +replaceMatch "\<QtDeclarative\>" "QtQml"
 +replaceMatch "\<asQDeclarativeContext" "asQQmlContext"
 +
 +# Replace any references to the 'declarative' module with 'qml'
 +echo "Replacing module declarative with qml:"
 +CONTAINERS=$(find "$MODIFY_DIR" \( -name \*\.pro -o -name \*\.pri \) | xargs grep -l -I "\<declarative\>")
 +for CONTAINER in $CONTAINERS
 +do
 +    echo "    $CONTAINER"
 +    TMP_FILE="$CONTAINER.tmp"
 +
 +    sed 's|\<declarative\>|qml|g' <"$CONTAINER" >"$TMP_FILE"
 +    mv "$TMP_FILE" "$CONTAINER"
 +done
 +echo
 +
 +echo "Replacements complete"
 +exit 0
Simple merge
index 0000000,7eea497..9539d2d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,23 +1,23 @@@
 -Some guidelines for QtDeclarative examples
++Some guidelines for QtQml examples
+ Snippets
+ ---
+ Snippets are snatches of QML code that won't even run on their own. They don't belong here, they belong in doc/src/snippets. They should be contained in files that will compile on their own, for automated syntax validation, but don't have to look like anything.
+ Examples
+ ---
+ Examples are large blocks of QML code that demonstrate a feature. You should be able to launch an example and visually see the feature take effect. Examples should be written in a small form, and should automatically activate any features. Ideally, when you run an example, you see the feature demonstrate itself over and over until you get bored and close the application using your platform's close window mechanism. Examples shouldn't contain their own close buttons or start screen, explanatory text should be kept to a minimum (show, not tell), and reserve interaction for demonstrating interactive elements. The code should be held to a high level of quality, and should be understandable by people new to QML.
+ Unless the demonstrated feature uses it, assume no interface devices other than a screen that can show a 320x480 rectangle and a generic pointing device (with the shared subset of mouse/touch functionality).
+ Groups of similar examples should be placed in one folder with a single launcher application, which uses the shared folder of common components.
+ The example, or launcher application in case of groups, should contain a qdoc comment explaining the example. The example or launcher should be buildable as a full C++ application and runnable with the standard qml file launcher. Usually this will consist primarily of using the macro found in shared.h.
+ Demos
+ ---
+ Demos are examples of creating full applications using QML. They should fit both a desktop and a mobile form factor, they should have their own start screen and method of exiting the application. They should be at a level of quality that you'd be comfortable submitting them to an app store for a platform of the appropriate hardware (screen size, input methods, etc.). The code should be written to a level that is easily understood and modified by a QML expert.
+ Demos should have a qdoc file in their directory explaining the demo at a high level. The demo should be buildable as a full C++ application and preferably runnable with the standard qml file launcher.
index 0000000,872fc81..e7b3637
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,84 +1,84 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ BorderImage {
+     id: button
+     property alias operation: buttonText.text
+     property string color: ""
+     Accessible.name: operation
+     Accessible.description: "This button does " + operation
+     Accessible.role: Accessible.Button
+     signal clicked
+     source: "images/button-" + color + ".png"; clip: true
+     border { left: 10; top: 10; right: 10; bottom: 10 }
+     Rectangle {
+         id: shade
+         anchors.fill: button; radius: 10; color: "black"; opacity: 0
+     }
+     Text {
+         id: buttonText
+         anchors.centerIn: parent; anchors.verticalCenterOffset: -1
+         font.pixelSize: parent.width > parent.height ? parent.height * .5 : parent.width * .5
+         style: Text.Sunken; color: "white"; styleColor: "black"; smooth: true
+     }
+     MouseArea {
+         id: mouseArea
+         anchors.fill: parent
+         onClicked: {
+             window.doOp(operation)
+             button.clicked()
+         }
+     }
+     states: State {
+         name: "pressed"; when: mouseArea.pressed == true
+         PropertyChanges { target: shade; opacity: .4 }
+     }
+ }
index 0000000,3333484..3dceeab
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,68 +1,68 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ BorderImage {
+     id: image
+     property alias text : displayText.text
+     property alias currentOperation : operationText
+     source: "images/display.png"
+     border { left: 10; top: 10; right: 10; bottom: 10 }
+     Text {
+         id: displayText
+         anchors {
+             right: parent.right; verticalCenter: parent.verticalCenter; verticalCenterOffset: -1
+             rightMargin: 6; left: operationText.right
+         }
+         font.pixelSize: parent.height * .6; text: "0"; horizontalAlignment: Text.AlignRight; elide: Text.ElideRight
+         color: "#343434"; smooth: true; font.bold: true
+     }
+     Text {
+         id: operationText
+         font.bold: true; font.pixelSize: parent.height * .7
+         color: "#343434"; smooth: true
+         anchors { left: parent.left; leftMargin: 6; verticalCenterOffset: -3; verticalCenter: parent.verticalCenter }
+     }
+ }
index 0000000,7e72f50..be65c77
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,136 +1,136 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Window 2.0
+ import "CalculatorCore"
+ import "CalculatorCore/calculator.js" as CalcEngine
+ Rectangle {
+     id: window
+     width: 640; height: 480
+     color: "#282828"
+     property string rotateLeft: "\u2939"
+     property string rotateRight: "\u2935"
+     property string leftArrow: "\u2190"
+     property string division : "\u00f7"
+     property string multiplication : "\u00d7"
+     property string squareRoot : "\u221a"
+     property string plusminus : "\u00b1"
+     function doOp(operation) { CalcEngine.doOperation(operation) }
+     focus: true
+     Keys.onPressed: doOp(event.text);
+     Item {
+         id: main
+         width: 640
+         height: 480
+         anchors.centerIn: parent
+         Column {
+             id: box; spacing: 8
+             anchors { fill: parent; topMargin: 6; bottomMargin: 6; leftMargin: 6; rightMargin: 6 }
+             Display {
+                 id: display
+                 width: box.width-3
+                 height: 64
+             }
+             Column {
+                 id: column; spacing: 6
+                 property real h: ((box.height - 72) / 6) - ((spacing * (6 - 1)) / 6)
+                 property real w: (box.width / 4) - ((spacing * (4 - 1)) / 4)
+                 Row {
+                     spacing: 6
+                     Button { width: column.w; height: column.h; color: 'purple'; operation: "Off" }
+                     Button { width: column.w; height: column.h; color: 'purple'; operation: leftArrow }
+                     Button { width: column.w; height: column.h; color: 'purple'; operation: "C" }
+                     Button { width: column.w; height: column.h; color: 'purple'; operation: "AC" }
+                 }
+                 Row {
+                     spacing: 6
+                     property real w: (box.width / 4) - ((spacing * (4 - 1)) / 4)
+                     Button { width: column.w; height: column.h; color: 'green'; operation: "mc" }
+                     Button { width: column.w; height: column.h; color: 'green'; operation: "m+" }
+                     Button { width: column.w; height: column.h; color: 'green'; operation: "m-" }
+                     Button { width: column.w; height: column.h; color: 'green'; operation: "mr" }
+                 }
+                 Grid {
+                     id: grid; rows: 5; columns: 5; spacing: 6
+                     property real w: (box.width / columns) - ((spacing * (columns - 1)) / columns)
+                     Button { width: grid.w; height: column.h; operation: "7"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "8"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "9"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: division }
+                     Button { width: grid.w; height: column.h; operation: squareRoot }
+                     Button { width: grid.w; height: column.h; operation: "4"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "5"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "6"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: multiplication }
+                     Button { width: grid.w; height: column.h; operation: "x^2" }
+                     Button { width: grid.w; height: column.h; operation: "1"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "2"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "3"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "-" }
+                     Button { width: grid.w; height: column.h; operation: "1/x" }
+                     Button { width: grid.w; height: column.h; operation: "0"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "." }
+                     Button { width: grid.w; height: column.h; operation: plusminus }
+                     Button { width: grid.w; height: column.h; operation: "+" }
+                     Button { width: grid.w; height: column.h; operation: "="; color: 'red' }
+                 }
+             }
+         }
+     }
+ }
index 0000000,b4fc372..7ee622f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,164 +1,164 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Window 2.0
+ import "CalculatorCore"
+ import "CalculatorCore/calculator.js" as CalcEngine
+ Rectangle {
+     id: window
+     width: 320; height: 480
+     color: "#282828"
+     property string rotateLeft: "\u2939"
+     property string rotateRight: "\u2935"
+     property string leftArrow: "\u2190"
+     property string division : "\u00f7"
+     property string multiplication : "\u00d7"
+     property string squareRoot : "\u221a"
+     property string plusminus : "\u00b1"
+     function doOp(operation) { CalcEngine.doOperation(operation) }
+     Item {
+         id: main
+         state: "orientation " + Screen.orientation
+         //Note: Assumes a primarily portrait device
+         property bool landscapeWindow: window.width > window.height 
+         property real baseWidth: landscapeWindow ? window.height : window.width
+         property real baseHeight: landscapeWindow ? window.width : window.height
+         property real rotationDelta: landscapeWindow ? -90 : 0
+         rotation: rotationDelta
+         width: main.baseWidth
+         height: main.baseHeight
+         anchors.centerIn: parent
+         Column {
+             id: box; spacing: 8
+             anchors { fill: parent; topMargin: 6; bottomMargin: 6; leftMargin: 6; rightMargin: 6 }
+             Display {
+                 id: display
+                 width: box.width-3
+                 height: 64
+             }
+             Column {
+                 id: column; spacing: 6
+                 property real h: ((box.height - 72) / 6) - ((spacing * (6 - 1)) / 6)
+                 property real w: (box.width / 4) - ((spacing * (4 - 1)) / 4)
+                 Row {
+                     spacing: 6
+                     Button { width: column.w; height: column.h; color: 'purple'; operation: "Off" }
+                     Button { width: column.w; height: column.h; color: 'purple'; operation: leftArrow }
+                     Button { width: column.w; height: column.h; color: 'purple'; operation: "C" }
+                     Button { width: column.w; height: column.h; color: 'purple'; operation: "AC" }
+                 }
+                 Row {
+                     spacing: 6
+                     property real w: (box.width / 4) - ((spacing * (4 - 1)) / 4)
+                     Button { width: column.w; height: column.h; color: 'green'; operation: "mc" }
+                     Button { width: column.w; height: column.h; color: 'green'; operation: "m+" }
+                     Button { width: column.w; height: column.h; color: 'green'; operation: "m-" }
+                     Button { width: column.w; height: column.h; color: 'green'; operation: "mr" }
+                 }
+                 Grid {
+                     id: grid; rows: 5; columns: 5; spacing: 6
+                     property real w: (box.width / columns) - ((spacing * (columns - 1)) / columns)
+                     Button { width: grid.w; height: column.h; operation: "7"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "8"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "9"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: division }
+                     Button { width: grid.w; height: column.h; operation: squareRoot }
+                     Button { width: grid.w; height: column.h; operation: "4"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "5"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "6"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: multiplication }
+                     Button { width: grid.w; height: column.h; operation: "x^2" }
+                     Button { width: grid.w; height: column.h; operation: "1"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "2"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "3"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "-" }
+                     Button { width: grid.w; height: column.h; operation: "1/x" }
+                     Button { width: grid.w; height: column.h; operation: "0"; color: 'blue' }
+                     Button { width: grid.w; height: column.h; operation: "." }
+                     Button { width: grid.w; height: column.h; operation: plusminus }
+                     Button { width: grid.w; height: column.h; operation: "+" }
+                     Button { width: grid.w; height: column.h; operation: "="; color: 'red' }
+                 }
+             }
+         }
+         states: [
+             State {
+                 name: "orientation " + Qt.LandscapeOrientation
+                 PropertyChanges { target: main; rotation: 90 + rotationDelta; width: main.baseHeight; height: main.baseWidth }
+             },
+             State {
+                 name: "orientation " + Qt.InvertedPortraitOrientation
+                 PropertyChanges { target: main; rotation: 180 + rotationDelta; }
+             },
+             State {
+                 name: "orientation " + Qt.InvertedLandscapeOrientation
+                 PropertyChanges { target: main; rotation: 270 + rotationDelta; width: main.baseHeight; height: main.baseWidth }
+             }
+         ]
+         transitions: Transition {
+             SequentialAnimation {
+                 RotationAnimation { direction: RotationAnimation.Shortest; duration: 300; easing.type: Easing.InOutQuint  }
+                 NumberAnimation { properties: "x,y,width,height"; duration: 300; easing.type: Easing.InOutQuint }
+             }
+         }
+     }
+ }
index 0000000,3bf3b8c..297d5cf
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,9 +1,9 @@@
 -QT += quick declarative
+ TEMPLATE = app
++QT += quick qml
+ SOURCES += main.cpp
+ target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/demos/calculator
+ qml.files = calculator-desktop.qml calculator-mobile.qml CalculatorCore
+ qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/demos/calculator
+ INSTALLS += target qml
index 0000000,c7f9b29..fafe14f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,66 +1,66 @@@
 -#include <QDeclarativeEngine>
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the examples of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #include <QGuiApplication>
+ #include <QStringList>
+ #include <QQuickView>
++#include <QQmlEngine>
+ void usage()
+ {
+     printf("Pass -desktop to use the Desktop UI");
+     exit(0);
+ }
+ int main(int argc, char* argv[])
+ {
+     QGuiApplication app(argc,argv);
+     QQuickView view;
+     QUrl launchFile = QUrl::fromLocalFile(QLatin1String("calculator-mobile.qml"));
+     if (app.arguments().contains(QLatin1String("-help")))
+         usage();
+     if (app.arguments().contains(QLatin1String("-desktop")))
+         launchFile =  QUrl::fromLocalFile(QLatin1String("calculator-desktop.qml"));
+     view.connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));
+     view.setSource(launchFile);
+     view.show();
+     return app.exec();
+ }
index 0000000,d6a8d3e..57f846a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,79 +1,79 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: container
+     signal clicked
+     property string text
+     BorderImage {
+         id: buttonImage
+         source: "images/toolbutton.sci"
+         width: container.width; height: container.height
+     }
+     BorderImage {
+         id: pressed
+         opacity: 0
+         source: "images/toolbutton.sci"
+         width: container.width; height: container.height
+     }
+     MouseArea {
+         id: mouseRegion
+         anchors.fill: buttonImage
+         onClicked: { container.clicked(); }
+     }
+     Text {
+         color: "white"
+         anchors.centerIn: buttonImage; font.bold: true; font.pixelSize: 15
+         text: container.text; style: Text.Raised; styleColor: "black"
+     }
+     states: [
+         State {
+             name: "Pressed"
+             when: mouseRegion.pressed == true
+             PropertyChanges { target: pressed; opacity: 1 }
+         }
+     ]
+ }
index 0000000,794d768..f8838bd
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,111 +1,111 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: wrapper; width: GridView.view.cellWidth; height: GridView.view.cellHeight
+     function photoClicked() {
+         imageDetails.photoTitle = title;
+         imageDetails.photoTags = tags;
+         imageDetails.photoWidth = photoWidth;
+         imageDetails.photoHeight = photoHeight;
+         imageDetails.photoType = photoType;
+         imageDetails.photoAuthor = photoAuthor;
+         imageDetails.photoDate = photoDate;
+         imageDetails.photoUrl = url;
+         imageDetails.rating = 0;
+         scaleMe.state = "Details";
+     }
+     Item {
+         anchors.centerIn: parent
+         scale: 0.0
+         Behavior on scale { NumberAnimation { easing.type: Easing.InOutQuad} }
+         id: scaleMe
+         Item {
+             width: 77; height: 77; anchors.centerIn: parent
+             Rectangle {
+                 id: whiteRect; width: 77; height: 77; color: "#dddddd"; smooth: true
+                 Image { id: thumb; source: imagePath; x: 1; y: 1; smooth: true }
+                 Image { source: "images/gloss.png" }
+             }
+         }
+         Connections {
+             target: toolBar
+             onButton2Clicked: if (scaleMe.state == 'Details' ) scaleMe.state = 'Show'
+         }
+         states: [
+             State {
+                 name: "Show"; when: thumb.status == Image.Ready
+                 PropertyChanges { target: scaleMe; scale: 1 }
+             },
+             State {
+                 name: "Details"
+                 PropertyChanges { target: scaleMe; scale: 1 }
+                 ParentChange { target: whiteRect; x: 10; y: 20; parent: imageDetails.frontContainer }
+                 PropertyChanges { target: background; state: "DetailedView" }
+             }
+         ]
+         transitions: [
+             Transition {
+                 from: "Show"; to: "Details"
+                 ParentAnimation {
+                     via: foreground
+                     NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad }
+                 }
+             },
+             Transition {
+                 from: "Details"; to: "Show"
+                 ParentAnimation {
+                     via: foreground
+                     NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad }
+                 }
+             }
+         ]
+     }
+     MouseArea { anchors.fill: wrapper; onClicked: photoClicked() }
+ }
index 0000000,83f2537..42b5e84
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,323 +1,323 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Flipable {
+     id: container
+     property alias frontContainer: containerFront
+     property string photoTitle: ""
+     property string photoTags: ""
+     property int photoWidth
+     property int photoHeight
+     property string photoType
+     property string photoAuthor
+     property string photoDate
+     property string photoUrl
+     property int rating: 2
+     property variant prevScale: 1.0
+     property int flipDuration: 1600
+     signal closed
+     transform: Rotation {
+         id: itemRotation
+         origin.x: container.width / 2;
+         axis.y: 1; axis.z: 0
+     }
+     front: Item {
+         id: containerFront; anchors.fill: container
+         Rectangle {
+             anchors.fill: parent
+             color: "black"; opacity: 0.4
+         }
+         Column {
+             spacing: 10
+             anchors {
+                 left: parent.left; leftMargin: 10
+                 right: parent.right; rightMargin: 10
+                 top: parent.top; topMargin: 120
+             }
+             Text { font.bold: true; color: "white"; elide: Text.ElideRight; text: container.photoTitle; width: parent.width }
+             Text { color: "white"; elide: Text.ElideRight; text: "Size: " + container.photoWidth + 'x' + container.photoHeight; width: parent.width }
+             Text { color: "white"; elide: Text.ElideRight; text: "Type: " + container.photoType; width: parent.width }
+             Text { color: "white"; elide: Text.ElideRight; text: "Author: " + container.photoAuthor; width: parent.width }
+             Text { color: "white"; elide: Text.ElideRight; text: "Published: " + container.photoDate; width: parent.width }
+             Text { color: "white"; elide: Text.ElideRight; text: container.photoTags == "" ? "" : "Tags: "; width: parent.width }
+             Text { color: "white"; elide: Text.ElideRight; text: container.photoTags; width: parent.width }
+         }
+     }
+     back: Item {
+         anchors.fill: container
+         Rectangle { anchors.fill: parent; color: "black"; opacity: 0.4 }
+         Progress {
+             anchors.centerIn: parent; width: 200; height: 22
+             progress: bigImage.progress; visible: bigImage.status != Image.Ready
+         }
+         Flickable {
+             id: flickable; anchors.fill: parent; clip: true
+             contentWidth: imageContainer.width; contentHeight: imageContainer.height
+             function updateMinimumScale() {
+                 if (bigImage.status == Image.Ready && bigImage.width != 0) {
+                     slider.minimum = Math.min(flickable.width / bigImage.width, flickable.height / bigImage.height);
+                     if (bigImage.width * slider.value > flickable.width) {
+                         var xoff = (flickable.width/2 + flickable.contentX) * slider.value / prevScale;
+                         flickable.contentX = xoff - flickable.width/2;
+                     }
+                     if (bigImage.height * slider.value > flickable.height) {
+                         var yoff = (flickable.height/2 + flickable.contentY) * slider.value / prevScale;
+                         flickable.contentY = yoff - flickable.height/2;
+                     }
+                     prevScale = slider.value;
+                 }
+             }
+             onWidthChanged: updateMinimumScale()
+             onHeightChanged: updateMinimumScale()
+             Item {
+                 id: imageContainer
+                 width: Math.max(bigImage.width * bigImage.scale, flickable.width);
+                 height: Math.max(bigImage.height * bigImage.scale, flickable.height);
+                 Image {
+                     id: bigImage; source: container.photoUrl; scale: slider.value
+                     anchors.centerIn: parent; smooth: !flickable.movingVertically
+                     onStatusChanged : {
+                         // Default scale shows the entire image.
+                         if (bigImage.status == Image.Ready && bigImage.width != 0) {
+                             slider.minimum = Math.min(flickable.width / bigImage.width, flickable.height / bigImage.height);
+                             prevScale = Math.min(slider.minimum, 1);
+                             slider.value = prevScale;
+                         }
+                         if (inBackState && bigImage.status == Image.Ready)
+                             effectBox.imageInAnim();
+                     }
+                     property bool inBackState: false
+                     onInBackStateChanged:{
+                         if(inBackState && bigImage.status == Image.Ready)
+                             effectBox.imageInAnim();
+                         else if (!inBackState && bigImage.status == Image.Ready)
+                             effectBox.imageOutAnim();
+                     }
+                 }
+                 ShaderEffectSource{
+                     id: pictureSource
+                     sourceItem: bigImage 
+                     smooth: true
+                     //Workaround: Doesn't work below lines
+                     width: bigImage.width
+                     height: bigImage.width
+                     visible: false
+                 }
+                 Turbulence{//only fill visible rect
+                     id: turbulence
+                     system: imageSystem
+                     anchors.fill: parent 
+                     strength: 240
+                     enabled: false
+                 }
+                 Item{
+                     id: effectBox
+                     width: bigImage.width * bigImage.scale
+                     height: bigImage.height * bigImage.scale
+                     anchors.centerIn: parent
+                     function imageInAnim(){
+                         bigImage.visible = false;
+                         noiseIn.visible = true;
+                         endEffectTimer.start();
+                     }
+                     function imageOutAnim(){
+                         bigImage.visible = false;
+                         noiseIn.visible = false;
+                         turbulence.enabled = true;
+                         endEffectTimer.start();
+                         pixelEmitter.burst(2048);
+                     }
+                     Timer{
+                         id: endEffectTimer
+                         interval: flipDuration
+                         repeat: false
+                         running: false
+                         onTriggered:{
+                             turbulence.enabled = false;
+                             noiseIn.visible = false;
+                             bigImage.visible = true;
+                         }
+                     }
+                     ShaderEffect{
+                         id: noiseIn
+                         anchors.fill: parent
+                         property real t: 0
+                         visible: false
+                         onVisibleChanged: tAnim.start()
+                         NumberAnimation{
+                             id: tAnim
+                             target: noiseIn
+                             property: "t"
+                             from: 0.0 
+                             to: 1.0
+                             duration: flipDuration
+                         }
+                         property variant source: pictureSource
+                         property variant noise: ShaderEffectSource{
+                             sourceItem:Image{
+                                 source: "images/noise.png"
+                             }
+                             hideSource: true
+                             smooth: false
+                         }
+                         fragmentShader:"
+                             uniform sampler2D noise;
+                             uniform sampler2D source;
+                             uniform highp float t;
+                             uniform lowp float qt_Opacity;
+                             varying highp vec2 qt_TexCoord0;
+                             void main(){
+                                 //Want to use noise2, but it always returns (0,0)?
+                                 if(texture2D(noise, qt_TexCoord0).w <= t)
+                                     gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity;
+                                 else
+                                     gl_FragColor = vec4(0.,0.,0.,0.);
+                             }
+                         "
+                     }
+                     ParticleSystem{
+                         id: imageSystem
+                     }
+                     Emitter{
+                         id: pixelEmitter
+                         system: imageSystem
+                         //anchors.fill: parent
+                         width: Math.min(bigImage.width * bigImage.scale, flickable.width);
+                         height: Math.min(bigImage.height * bigImage.scale, flickable.height);
+                         anchors.centerIn: parent
+                         size: 4
+                         lifeSpan: flipDuration
+                         emitRate: 2048
+                         enabled: false
+                     }
+                     CustomParticle{
+                         id: blowOut
+                         system: imageSystem
+                         property real maxWidth: effectBox.width
+                         property real maxHeight: effectBox.height
+                         vertexShader:"
+                             uniform highp float maxWidth;
+                             uniform highp float maxHeight;
+                             varying highp vec2 fTex2;
+                             void main() {
+                                 defaultMain();
+                                 fTex2 = vec2(qt_ParticlePos.x / maxWidth, qt_ParticlePos.y / maxHeight);
+                             }
+                         "
+                         property variant pictureTexture: pictureSource
+                         fragmentShader: "
+                             uniform lowp float qt_Opacity;
+                             uniform sampler2D pictureTexture;
+                             varying highp vec2 fTex2;
+                             void main() {
+                                 gl_FragColor = texture2D(pictureTexture, fTex2) * qt_Opacity;
+                         }"
+                     }
+                 }
+             }
+         }
+         Text {
+             text: "Image Unavailable"
+             visible: bigImage.status == Image.Error
+             anchors.centerIn: parent; color: "white"; font.bold: true
+         }
+         Slider {
+             id: slider; visible: { bigImage.status == Image.Ready && maximum > minimum }
+             anchors {
+                 bottom: parent.bottom; bottomMargin: 65
+                 left: parent.left; leftMargin: 25
+                 right: parent.right; rightMargin: 25
+             }
+             onValueChanged: {
+                 if (bigImage.width * value > flickable.width) {
+                     var xoff = (flickable.width/2 + flickable.contentX) * value / prevScale;
+                     flickable.contentX = xoff - flickable.width/2;
+                 }
+                 if (bigImage.height * value > flickable.height) {
+                     var yoff = (flickable.height/2 + flickable.contentY) * value / prevScale;
+                     flickable.contentY = yoff - flickable.height/2;
+                 }
+                 prevScale = value;
+             }
+         }
+     }
+     states: State {
+         name: "Back"
+         PropertyChanges { target: itemRotation; angle: 180 }
+         PropertyChanges { target: toolBar; button2Visible: false }
+         PropertyChanges { target: toolBar; button1Label: "Back" }
+         PropertyChanges { target: bigImage; inBackState: true }
+     }
+     transitions: Transition {
+         SequentialAnimation {
+             PropertyAction { target: bigImage; property: "smooth"; value: false }
+             NumberAnimation { easing.type: Easing.InOutQuad; properties: "angle"; duration: flipDuration }
+             PropertyAction { target: bigImage; property: "smooth"; value: !flickable.movingVertically }
+         }
+     }
+ }
index 0000000,9c23915..00f837f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,64 +1,64 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Component {
+     Item {
+         id: wrapper; width: wrapper.ListView.view.width; height: 86
+         Item {
+             id: moveMe
+             Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+             Rectangle {
+                 x: 6; y: 4; width: 77; height: 77; color: "white"; smooth: true
+                 Image { source: imagePath; x: 1; y: 1 }
+                 Image { source: "images/gloss.png" }
+             }
+             Column {
+                 x: 92; width: wrapper.ListView.view.width - 95; y: 15; spacing: 2
+                 Text { text: title; color: "white"; width: parent.width; font.pixelSize: 14; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black" }
+                 Text { text: photoAuthor; width: parent.width; font.pixelSize: 14; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
+                 Text { text: photoDate; width: parent.width; font.pixelSize: 14; elide: Text.ElideRight; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
+             }
+         }
+     }
+ }
index 0000000,81f1e79..ed2629b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,88 +1,88 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item{
+     id: container
+     property variant progress: 0
+     Rectangle {
+         anchors.fill: parent; smooth: true
+         border.color: "white"; border.width: 0; radius: height/2 - 2
+         gradient: Gradient {
+             GradientStop { position: 0; color: "#66343434" }
+             GradientStop { position: 1.0; color: "#66000000" }
+         }
+     }
+     ParticleSystem{
+         running: container.visible
+         id: barSys
+     }
+     ImageParticle{
+         color: "lightsteelblue"
+         alpha: 0.1
+         colorVariation: 0.05
+         source: "images/particle.png"
+         system: barSys
+     }
+     Emitter{
+         y: 2; height: parent.height-4;
+         x: 2; width: Math.max(parent.width * progress - 4, 0);
+         speed: AngleDirection{ angleVariation: 180; magnitudeVariation: 12 }
+         system: barSys
+         emitRate: width;
+         lifeSpan: 1000
+         size: 20
+         sizeVariation: 4
+         endSize: 12
+         maximumEmitted: parent.width;
+     }
+     Text {
+         text: Math.round(progress * 100) + "%"
+         anchors.horizontalCenter: parent.horizontalCenter
+         anchors.verticalCenter: parent.verticalCenter
+         color: Qt.rgba(1.0, 1.0 - progress, 1.0 - progress,0.9); font.bold: true; font.pixelSize: 15
+     }
+ }
index 0000000,f28a23d..51cea49
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,64 +1,64 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.XmlListModel 2.0
+ XmlListModel {
+     property string tags : ""
+     function encodeTags(x) { return encodeURIComponent(x.replace(' ',',')); }
+     source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+encodeTags(tags)+"&" : "")+"format=rss2"
+     query: "/rss/channel/item"
+     namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
+     XmlRole { name: "title"; query: "title/string()" }
+     XmlRole { name: "imagePath"; query: "media:thumbnail/@url/string()" }
+     XmlRole { name: "url"; query: "media:content/@url/string()" }
+     XmlRole { name: "description"; query: "description/string()" }
+     XmlRole { name: "tags"; query: "media:category/string()" }
+     XmlRole { name: "photoWidth"; query: "media:content/@width/string()" }
+     XmlRole { name: "photoHeight"; query: "media:content/@height/string()" }
+     XmlRole { name: "photoType"; query: "media:content/@type/string()" }
+     XmlRole { name: "photoAuthor"; query: "author/string()" }
+     XmlRole { name: "photoDate"; query: "pubDate/string()" }
+ }
index 0000000,388e43d..7c62ad0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,81 +1,81 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: container
+     property variant flickableArea
+     Rectangle {
+         radius: 5
+         color: "black"
+         opacity: 0.3
+         border.color: "white"
+         border.width: 2
+         x: 0
+         y: flickableArea.visibleArea.yPosition * container.height
+         width: parent.width
+         height: flickableArea.visibleArea.heightRatio * container.height
+     }
+     states: [
+         State {
+             name: "show"
+             when: flickableArea.movingVertically
+             PropertyChanges {
+                 target: container
+                 opacity: 1
+             }
+         }
+     ]
+     transitions: [
+         Transition {
+             from: "*"
+             to: "*"
+             NumberAnimation {
+                 target: container
+                 properties: "opacity"
+                 duration: 400
+             }
+         }
+     ]
+ }
index 0000000,0f9e8b2..c4e7436
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,91 +1,91 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: slider; width: 400; height: 16
+     // value is read/write.
+     property real value: 1
+     onValueChanged: updatePos();
+     property real maximum: 1
+     property real minimum: 1
+     property int xMax: width - handle.width - 4
+     onXMaxChanged: updatePos();
+     onMinimumChanged: updatePos();
+     function updatePos() {
+         if (maximum > minimum) {
+             var pos = 2 + (value - minimum) * slider.xMax / (maximum - minimum);
+             pos = Math.min(pos, width - handle.width - 2);
+             pos = Math.max(pos, 2);
+             handle.x = pos;
+         } else {
+             handle.x = 2;
+         }
+     }
+     Rectangle {
+         anchors.fill: parent
+         border.color: "white"; border.width: 0; radius: 8
+         gradient: Gradient {
+             GradientStop { position: 0.0; color: "#66343434" }
+             GradientStop { position: 1.0; color: "#66000000" }
+         }
+     }
+     Rectangle {
+         id: handle; smooth: true
+         y: 2; width: 30; height: slider.height-4; radius: 6
+         gradient: Gradient {
+             GradientStop { position: 0.0; color: "lightgray" }
+             GradientStop { position: 1.0; color: "gray" }
+         }
+         MouseArea {
+             id: mouse
+             anchors.fill: parent; drag.target: parent
+             drag.axis: Drag.XAxis; drag.minimumX: 2; drag.maximumX: slider.xMax+2
+             onPositionChanged: { value = (maximum - minimum) * (handle.x-2) / slider.xMax + minimum; }
+         }
+     }
+ }
index 0000000,3dab005..223939f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,128 +1,128 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: titleBar
+     property string untaggedString: "Uploads from everyone"
+     property string taggedString: "Recent uploads tagged "
+     BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
+     Item {
+         id: container
+         width: (parent.width * 2) - 55 ; height: parent.height
+         function accept() {
+             imageDetails.closed()
+             titleBar.state = ""
+             background.state = ""
+             rssModel.tags = editor.text
+         }
+         Image {
+             id: quitButton
+             anchors.left: parent.left//; anchors.leftMargin: 0
+             anchors.verticalCenter: parent.verticalCenter
+             source: "images/quit.png"
+             MouseArea {
+                 anchors.fill: parent
+                 onClicked: Qt.quit()
+             }
+         }
+         Text {
+             id: categoryText
+             anchors {
+                 left: quitButton.right; right: tagButton.left; leftMargin: 10; rightMargin: 10
+                 verticalCenter: parent.verticalCenter
+             }
+             elide: Text.ElideLeft
+             text: (rssModel.tags=="" ? untaggedString : taggedString + rssModel.tags)
+             font.bold: true; font.pixelSize: 15; color: "White"; style: Text.Raised; styleColor: "Black"
+         }
+         Button {
+             id: tagButton; x: titleBar.width - 50; width: 45; height: 32; text: "..."
+             onClicked: if (titleBar.state == "Tags") container.accept(); else titleBar.state = "Tags"
+             anchors.verticalCenter: parent.verticalCenter
+         }
+         Item {
+             id: lineEdit
+             y: 4; height: parent.height - 9
+             anchors { left: tagButton.right; leftMargin: 5; right: parent.right; rightMargin: 5 }
+             BorderImage { source: "images/lineedit.sci"; anchors.fill: parent }
+             TextInput {
+                 id: editor
+                 anchors {
+                     left: parent.left; right: parent.right; leftMargin: 10; rightMargin: 10
+                     verticalCenter: parent.verticalCenter
+                 }
+                 cursorVisible: true; font.bold: true
+                 color: "#151515"; selectionColor: "Green"
+             }
+             Keys.forwardTo: [ (returnKey), (editor)]
+             Item {
+                 id: returnKey
+                 Keys.onReturnPressed: container.accept()
+                 Keys.onEnterPressed: container.accept()
+                 Keys.onEscapePressed: titleBar.state = ""
+             }
+         }
+     }
+     states: State {
+         name: "Tags"
+         PropertyChanges { target: container; x: -tagButton.x + 5 }
+         PropertyChanges { target: tagButton; text: "OK" }
+         PropertyChanges { target: editor; focus: true }
+     }
+     transitions: Transition {
+         NumberAnimation { properties: "x"; easing.type: Easing.InOutQuad }
+     }
+ }
index 0000000,e82be63..356993b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,69 +1,69 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: toolbar
+     property alias button1Label: button1.text
+     property alias button2Label: button2.text
+     property alias button2Visible: button2.visible
+     signal button1Clicked
+     signal button2Clicked
+     BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
+     Row {
+         anchors.right: parent.right; anchors.rightMargin: 5; y: 3; height: 32; spacing: 30
+         Button {
+             id: button1
+             width: 140; height: 32
+             onClicked: toolbar.button1Clicked()
+         }
+         Button {
+             id: button2; width: 140; height: 32
+             onClicked: toolbar.button2Clicked()
+         }
+     }
+ }
index 0000000,00a777b..0b068c0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,154 +1,154 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Package {
+     function photoClicked() {
+         imageDetails.photoTitle = title;
+         imageDetails.photoTags = tags;
+         imageDetails.photoWidth = photoWidth;
+         imageDetails.photoHeight = photoHeight;
+         imageDetails.photoType = photoType;
+         imageDetails.photoAuthor = photoAuthor;
+         imageDetails.photoDate = photoDate;
+         imageDetails.photoUrl = url;
+         imageDetails.rating = 0;
+         scaleMe.state = "Details";
+     }
+     Item {
+         id: gridwrapper;
+         width: GridView.view.cellWidth; height: GridView.view.cellHeight
+         Package.name: "grid"
+     }
+     Item {
+         id: streamwrapper;
+         width: 80; height: 80
+         Package.name: "stream"
+     }
+     Item {
+         //anchors.centerIn: parent//Doesn't animate :(
+         width: 80; height: 80
+         scale: 0.0
+         Behavior on scale { NumberAnimation { easing.type: Easing.InOutQuad} }
+         id: scaleMe
+         Item {
+             id: whiteRectContainer
+             width: 77; height: 77; anchors.centerIn: parent
+             Rectangle {
+                 id: whiteRect; width: 77; height: 77; color: "#dddddd"; smooth: true
+                 x:0; y:0
+                 Image { id: thumb; source: imagePath; x: 1; y: 1; smooth: true }
+                 Image { source: "images/gloss.png" }
+                 MouseArea { anchors.fill: parent; onClicked: photoClicked() }
+             }
+         }
+         Connections {
+             target: toolBar
+             onButton2Clicked: if (scaleMe.state == 'Details' ) scaleMe.state = 'Show'
+         }
+             state: 'inStream'
+         states: [
+             State {
+                 name: "Show"; when: thumb.status == Image.Ready
+                 PropertyChanges { target: scaleMe; scale: 1; }
+             },
+             State {
+                 name: "Details"
+                 PropertyChanges { target: scaleMe; scale: 1 }
+                 ParentChange { target: whiteRect; x: 10; y: 20; parent: imageDetails.frontContainer }
+                 PropertyChanges { target: background; state: "DetailedView" }
+             }
+         ]
+         transitions: [
+             Transition {
+                 from: "Show"; to: "Details"
+                 ParentAnimation {
+                     via: foreground
+                     NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad }
+                 }
+             },
+             Transition {
+                 from: "Details"; to: "Show"
+                 SequentialAnimation{
+                     ParentAnimation {
+                         via: foreground
+                         NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad }
+                     }
+                 }
+             }
+         ]
+         Item{
+             id: stateContainer
+             states: [
+                 State {
+                     name: 'inStream'
+                     when: screen.inGridView == false
+                     ParentChange { 
+                         target: scaleMe; parent: streamwrapper 
+                         x: 0; y: 0; 
+                     }
+                 },
+                 State {
+                     name: 'inGrid'
+                     when: screen.inGridView == true
+                     ParentChange {
+                         target: scaleMe; parent: gridwrapper
+                         x: 0; y: 0;
+                     }
+                 }
+             ]
+             transitions: [
+                 Transition {
+                     ParentAnimation {
+                         NumberAnimation { target: scaleMe; properties: 'x,y,width,height'; duration: 300 }
+                     }
+                 }
+             ]
+         }
+     }
+ }
index 0000000,ae06957..b95b1c9
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,52 +1,52 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     width: 480; height: 320
+     Loader {
+         y: 320; rotation: -90
+         transformOrigin: Item.TopLeft
+         source: "flickr.qml"
+     }
+ }
index 0000000,74c41f1..98ca519
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,158 +1,158 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ import "content"
+ Item {
+     id: screen; width: 320; height: 480
+     property bool inGridView : true
+     Rectangle {
+         id: background
+         anchors.fill: parent; color: "#343434";
+         Image { source: "content/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 0.3 }
+         ParticleSystem {
+             id: bgParticles
+             anchors.fill: parent
+             ImageParticle {
+                 groups: ["trail"]
+                 source: "content/images/particle.png"
+                 color: "#1A1A6F"
+                 alpha: 0.1
+                 colorVariation: 0.01
+                 blueVariation: 0.8
+             }
+             Emitter {
+                 group: "drops"
+                 width: parent.width
+                 emitRate: 0.5
+                 lifeSpan: 20000
+                 startTime: 16000
+                 speed: PointDirection{
+                     y: {screen.height/18}
+                 }
+             }
+             TrailEmitter {
+                 follow: "drops"
+                 group: "trail"
+                 emitRatePerParticle: 18
+                 size: 32
+                 endSize: 0
+                 sizeVariation: 4
+                 lifeSpan: 1200
+                 anchors.fill: parent
+                 emitWidth: 16
+                 emitHeight: 16
+                 emitShape: EllipseShape{}
+             }
+         }
+         VisualDataModel{
+             id: vdm
+             delegate: UnifiedDelegate{}
+             model: RssModel { id: rssModel }
+         }
+         Item {
+             id: views
+             width: parent.width
+             anchors.top: titleBar.bottom; anchors.bottom: toolBar.top
+             GridView {
+                 id: photoGridView; model: vdm.parts.grid
+                 cacheBuffer: 1000
+                 cellWidth: (parent.width-2)/4; cellHeight: cellWidth; width: parent.width; height: parent.height
+             }
+             states: State {
+                 name: "GridView"; when: state.inGridView == true
+             }
+             transitions: Transition {
+                 NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad }
+             }
+             ImageDetails { id: imageDetails; width: parent.width; anchors.left: views.right; height: parent.height }
+             Item { id: foreground; anchors.fill: parent }
+         }
+         TitleBar { id: titleBar; width: parent.width; height: 40; opacity: 0.9 }
+         ToolBar {
+             id: toolBar
+             height: 40; anchors.bottom: parent.bottom; width: parent.width; opacity: 0.9
+             button1Label: "Update"; button2Label: "View mode"
+             onButton1Clicked: rssModel.reload()
+             onButton2Clicked: if (screen.inGridView == true) screen.inGridView = false; else screen.inGridView = true
+         }
+         Connections {
+             target: imageDetails
+             onClosed: {
+                 if (background.state == "DetailedView") {
+                     background.state = '';
+                     imageDetails.photoUrl = "";
+                 }
+             }
+         }
+         states: State {
+             name: "DetailedView"
+             PropertyChanges { target: views; x: -parent.width }
+             PropertyChanges { target: toolBar; button1Label: "View..." }
+             PropertyChanges {
+                 target: toolBar
+                 onButton1Clicked: if (imageDetails.state=='') imageDetails.state='Back'; else imageDetails.state=''
+             }
+             PropertyChanges { target: toolBar; button2Label: "Back" }
+             PropertyChanges { target: toolBar; onButton2Clicked: imageDetails.closed() }
+         }
+         transitions: Transition {
+             NumberAnimation { properties: "x"; duration: 500; easing.type: Easing.InOutQuad }
+         }
+     }
+ }
index 0000000,0983b68..a1b4292
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,69 +1,69 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     property bool explode : false
+     ParticleSystem {
+         width: 40
+         height: 40
+         ImageParticle {
+             groups: ["star"]
+             source: "file:MinehuntCore/pics/star.png" // TODO: Use qrc path once QTBUG-21129 is fixed
+         }
+         Emitter {
+             id: particles
+             enabled: false
+             anchors.centerIn: parent
+             group: "star"
+             speed: AngleDirection { angleVariation: 360; magnitude: 150; magnitudeVariation: 50 }
+             emitRate: 200
+             z: 100
+             lifeSpan: 1000
+         }
+     }
+     states: State { name: "exploding"; when: explode
+         StateChangeScript { script: particles.burst(200); }
+     }
+ }
index 0000000,14c1f51..1180b6f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,128 +1,128 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Flipable {
+     id: flipable
+     property int angle: 0
+     width: 40;  height: 40
+     transform: Rotation { origin.x: 20; origin.y: 20; axis.x: 1; axis.z: 0; angle: flipable.angle }
+     front: Image {
+         source: "pics/front.png"; width: 40; height: 40
+         Image {
+             anchors.centerIn: parent
+             source: "pics/flag.png"; opacity: modelData.hasFlag
+             Behavior on opacity { NumberAnimation {} }
+         }
+     }
+     back: Image {
+         source: "pics/back.png"
+         width: 40; height: 40
+         Text {
+             anchors.centerIn: parent
+             text: modelData.hint; color: "white"; font.bold: true
+             opacity: !modelData.hasMine && modelData.hint > 0
+         }
+         Image {
+             anchors.centerIn: parent
+             source: "pics/bomb.png"; opacity: modelData.hasMine
+         }
+         Explosion { id: expl }
+     }
+     states: State {
+         name: "back"; when: modelData.flipped
+         PropertyChanges { target: flipable; angle: 180 }
+     }
+     property real pauseDur: 250
+     transitions: Transition {
+         SequentialAnimation {
+             ScriptAction {
+                 script: {
+                     var ret = Math.abs(flipable.x - field.clickx)
+                         + Math.abs(flipable.y - field.clicky);
+                     if (modelData.hasMine && modelData.flipped)
+                         pauseDur = ret * 3
+                     else
+                         pauseDur = ret
+                 }
+             }
+             PauseAnimation {
+                 duration: pauseDur
+             }
+             RotationAnimation { easing.type: Easing.InOutQuad }
+             ScriptAction { script: if (modelData.hasMine && modelData.flipped) { expl.explode = true } }
+         }
+     }
+     MouseArea {
+         anchors.fill: parent
+         acceptedButtons: Qt.LeftButton | Qt.RightButton
+         onClicked: {
+             field.clickx = flipable.x
+             field.clicky = flipable.y
+             var row = Math.floor(index / 9)
+             var col = index - (Math.floor(index / 9) * 9)
+             if (mouse.button == undefined || mouse.button == Qt.RightButton) {
+                 flag(row, col)
+             } else {
+                 flip(row, col)
+             }
+         }
+         onPressAndHold: {
+             field.clickx = flipable.x
+             field.clicky = flipable.y
+             var row = Math.floor(index / 9)
+             var col = index - (Math.floor(index / 9) * 9)
+             flag(row, col)
+         }
+     }
+ }
index 0000000,47c0436..0aa11a1
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,64 +1,64 @@@
 -#include <QtDeclarative/QDeclarativeContext>
 -#include <QtDeclarative/QDeclarativeEngine>
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the demonstration applications of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #include <QtGui/QGuiApplication>
+ #include <QtQuick/qquickview.h>
++#include <QtQml/QQmlContext>
++#include <QtQml/QQmlEngine>
+ #include "minehunt.h"
+ int main(int argc, char *argv[])
+ {
+     QGuiApplication app(argc, argv);
+     QQuickView canvas;
+     qmlRegisterType<TileData>();
+     MinehuntGame* game = new MinehuntGame();
+     canvas.setResizeMode(QQuickView::SizeRootObjectToView);
+     canvas.engine()->rootContext()->setContextObject(game);
+     canvas.setSource(QString("qrc:///minehunt.qml"));
+     QObject::connect(canvas.engine(), SIGNAL(quit()), &app, SLOT(quit()));
+     canvas.show();
+     return app.exec();
+ }
index 0000000,facbec3..cde3027
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,221 +1,221 @@@
 -void tilesPropAppend(QDeclarativeListProperty<TileData>* prop, TileData* value)
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the demonstration applications of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #include <stdlib.h>
+ #include <QTime>
+ #include <QTimer>
+ #include "minehunt.h"
 -int tilesPropCount(QDeclarativeListProperty<TileData>* prop)
++void tilesPropAppend(QQmlListProperty<TileData>* prop, TileData* value)
+ {
+     Q_UNUSED(prop);
+     Q_UNUSED(value);
+     return; //Append not supported
+ }
 -TileData* tilesPropAt(QDeclarativeListProperty<TileData>* prop, int index)
++int tilesPropCount(QQmlListProperty<TileData>* prop)
+ {
+     return static_cast<QList<TileData*>*>(prop->data)->count();
+ }
 -QDeclarativeListProperty<TileData> MinehuntGame::tiles(){
 -    return QDeclarativeListProperty<TileData>(this, &_tiles, &tilesPropAppend,
++TileData* tilesPropAt(QQmlListProperty<TileData>* prop, int index)
+ {
+     return static_cast<QList<TileData*>*>(prop->data)->at(index);
+ }
++QQmlListProperty<TileData> MinehuntGame::tiles(){
++    return QQmlListProperty<TileData>(this, &_tiles, &tilesPropAppend,
+             &tilesPropCount, &tilesPropAt, 0);
+ }
+ MinehuntGame::MinehuntGame()
+ : numCols(9), numRows(9), playing(true), won(false)
+ {
+     setObjectName("mainObject");
+     srand(QTime(0,0,0).secsTo(QTime::currentTime()));
+     //initialize array
+     for(int ii = 0; ii < numRows * numCols; ++ii) {
+         _tiles << new TileData;
+     }
+     reset();
+ }
+ void MinehuntGame::setBoard()
+ {
+     foreach(TileData* t, _tiles){
+         t->setHasMine(false);
+         t->setHint(-1);
+     }
+     //place mines
+     int mines = nMines;
+     remaining = numRows*numCols-mines;
+     while ( mines ) {
+         int col = int((double(rand()) / double(RAND_MAX)) * numCols);
+         int row = int((double(rand()) / double(RAND_MAX)) * numRows);
+         TileData* t = tile( row, col );
+         if (t && !t->hasMine()) {
+             t->setHasMine( true );
+             mines--;
+         }
+     }
+     //set hints
+     for (int r = 0; r < numRows; r++)
+         for (int c = 0; c < numCols; c++) {
+             TileData* t = tile(r, c);
+             if (t && !t->hasMine()) {
+                 int hint = getHint(r,c);
+                 t->setHint(hint);
+             }
+         }
+     setPlaying(true);
+ }
+ void MinehuntGame::reset()
+ {
+     foreach(TileData* t, _tiles){
+         t->unflip();
+         t->setHasFlag(false);
+     }
+     nMines = 12;
+     nFlags = 0;
+     emit numMinesChanged();
+     emit numFlagsChanged();
+     setPlaying(false);
+     QTimer::singleShot(600,this, SLOT(setBoard()));
+ }
+ int MinehuntGame::getHint(int row, int col)
+ {
+     int hint = 0;
+     for (int c = col-1; c <= col+1; c++)
+         for (int r = row-1; r <= row+1; r++) {
+             TileData* t = tile(r, c);
+             if (t && t->hasMine())
+                 hint++;
+         }
+     return hint;
+ }
+ bool MinehuntGame::flip(int row, int col)
+ {
+     if(!playing)
+         return false;
+     TileData *t = tile(row, col);
+     if (!t || t->hasFlag())
+         return false;
+     if(t->flipped()){
+         int flags = 0;
+         for (int c = col-1; c <= col+1; c++)
+             for (int r = row-1; r <= row+1; r++) {
+                 TileData *nearT = tile(r, c);
+                 if(!nearT || nearT == t)
+                     continue;
+                 if(nearT->hasFlag())
+                     flags++;
+             }
+         if(!t->hint() || t->hint() != flags)
+             return false;
+         for (int c = col-1; c <= col+1; c++)
+             for (int r = row-1; r <= row+1; r++) {
+                 TileData *nearT = tile(r, c);
+                 if (nearT && !nearT->flipped() && !nearT->hasFlag()) {
+                     flip( r, c );
+                 }
+             }
+         return true;
+     }
+     t->flip();
+     if (t->hint() == 0) {
+         for (int c = col-1; c <= col+1; c++)
+             for (int r = row-1; r <= row+1; r++) {
+                 TileData* t = tile(r, c);
+                 if (t && !t->flipped()) {
+                     flip( r, c );
+                 }
+             }
+     }
+     if(t->hasMine()){
+         for (int r = 0; r < numRows; r++)//Flip all other mines
+             for (int c = 0; c < numCols; c++) {
+                 TileData* t = tile(r, c);
+                 if (t && t->hasMine()) {
+                     flip(r, c);
+                 }
+             }
+         won = false;
+         hasWonChanged();
+         setPlaying(false);
+         return true;
+     }
+     remaining--;
+     if(!remaining){
+         won = true;
+         hasWonChanged();
+         setPlaying(false);
+         return true;
+     }
+     return true;
+ }
+ bool MinehuntGame::flag(int row, int col)
+ {
+     TileData *t = tile(row, col);
+     if(!t || !playing || t->flipped())
+         return false;
+     t->setHasFlag(!t->hasFlag());
+     nFlags += (t->hasFlag()?1:-1);
+     emit numFlagsChanged();
+     return true;
+ }
index 0000000,a0ae23f..34bab71
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,129 +1,129 @@@
 -#include <qdeclarative.h>
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the demonstration applications of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
 -    Q_PROPERTY(QDeclarativeListProperty<TileData> tiles READ tiles CONSTANT)
 -    QDeclarativeListProperty<TileData> tiles();
++#include <qqml.h>
+ class TileData : public QObject
+ {
+     Q_OBJECT
+ public:
+     TileData() : _hasFlag(false), _hasMine(false), _hint(-1), _flipped(false) {}
+     Q_PROPERTY(bool hasFlag READ hasFlag WRITE setHasFlag NOTIFY hasFlagChanged)
+     bool hasFlag() const { return _hasFlag; }
+     Q_PROPERTY(bool hasMine READ hasMine NOTIFY hasMineChanged)
+     bool hasMine() const { return _hasMine; }
+     Q_PROPERTY(int hint READ hint NOTIFY hintChanged)
+     int hint() const { return _hint; }
+     Q_PROPERTY(bool flipped READ flipped NOTIFY flippedChanged())
+     bool flipped() const { return _flipped; }
+     void setHasFlag(bool flag) {if(flag==_hasFlag) return; _hasFlag = flag; emit hasFlagChanged();}
+     void setHasMine(bool mine) {if(mine==_hasMine) return; _hasMine = mine; emit hasMineChanged();}
+     void setHint(int hint) { if(hint == _hint) return; _hint = hint; emit hintChanged(); }
+     void flip() { if (_flipped) return; _flipped = true; emit flippedChanged(); }
+     void unflip() { if(!_flipped) return; _flipped = false; emit flippedChanged(); }
+ signals:
+     void flippedChanged();
+     void hasFlagChanged();
+     void hintChanged();
+     void hasMineChanged();
+ private:
+     bool _hasFlag;
+     bool _hasMine;
+     int _hint;
+     bool _flipped;
+ };
+ class MinehuntGame : public QObject
+ {
+     Q_OBJECT
+ public:
+     MinehuntGame();
++    Q_PROPERTY(QQmlListProperty<TileData> tiles READ tiles CONSTANT)
++    QQmlListProperty<TileData> tiles();
+     Q_PROPERTY(bool isPlaying READ isPlaying NOTIFY isPlayingChanged)
+     bool isPlaying() {return playing;}
+     Q_PROPERTY(bool hasWon READ hasWon NOTIFY hasWonChanged)
+     bool hasWon() {return won;}
+     Q_PROPERTY(int numMines READ numMines NOTIFY numMinesChanged)
+     int numMines() const{return nMines;}
+     Q_PROPERTY(int numFlags READ numFlags NOTIFY numFlagsChanged)
+     int numFlags() const{return nFlags;}
+ public slots:
+     Q_INVOKABLE bool flip(int row, int col);
+     Q_INVOKABLE bool flag(int row, int col);
+     void setBoard();
+     void reset();
+ signals:
+     void isPlayingChanged();
+     void hasWonChanged();
+     void numMinesChanged();
+     void numFlagsChanged();
+ private:
+     bool onBoard( int r, int c ) const { return r >= 0 && r < numRows && c >= 0 && c < numCols; }
+     TileData *tile( int row, int col ) { return onBoard(row, col) ? _tiles[col+numRows*row] : 0; }
+     int getHint(int row, int col);
+     void setPlaying(bool b){if(b==playing) return; playing=b; emit isPlayingChanged();}
+     QList<TileData *> _tiles;
+     int numCols;
+     int numRows;
+     bool playing;
+     bool won;
+     int remaining;
+     int nMines;
+     int nFlags;
+ };
index 0000000,81b6b80..78e874d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,5 +1,5 @@@
 -QT += declarative quick
++QT += qml quick
+ HEADERS += minehunt.h
+ SOURCES += main.cpp minehunt.cpp
+ RESOURCES = minehunt.qrc
index 0000000,7c4948a..42dc408
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,112 +1,112 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import "MinehuntCore" 2.0
+ Item {
+     id: field
+     property int clickx: 0
+     property int clicky: 0
+     width: 450; height: 450
+     Image { source: "MinehuntCore/pics/background.png"; anchors.fill: parent; fillMode: Image.Tile }
+     Grid {
+         anchors.horizontalCenter: parent.horizontalCenter
+         columns: 9; spacing: 1
+         Repeater {
+             id: repeater
+             model: tiles
+             delegate: Tile {}
+         }
+     }
+     Row {
+         id: gamedata
+         x: 20; spacing: 20
+         anchors.bottom: field.bottom; anchors.bottomMargin: 15
+         Image {
+             source: "MinehuntCore/pics/quit.png"
+             scale: quitMouse.pressed ? 0.8 : 1.0
+             smooth: quitMouse.pressed
+             y: 10
+             MouseArea {
+                 id: quitMouse
+                 anchors.fill: parent
+                 anchors.margins: -20
+                 onClicked: Qt.quit()
+             }
+         }
+         Column {
+             spacing: 2
+             Image { source: "MinehuntCore/pics/bomb-color.png" }
+             Text { anchors.horizontalCenter: parent.horizontalCenter; color: "white"; text: numMines }
+         }
+         Column {
+             spacing: 2
+             Image { source: "MinehuntCore/pics/flag-color.png" }
+             Text { anchors.horizontalCenter: parent.horizontalCenter; color: "white"; text: numFlags }
+         }
+     }
+     Image {
+         anchors.bottom: field.bottom; anchors.bottomMargin: 15
+         anchors.right: field.right; anchors.rightMargin: 20
+         source: isPlaying ? 'MinehuntCore/pics/face-smile.png' :
+         hasWon ? 'MinehuntCore/pics/face-smile-big.png': 'MinehuntCore/pics/face-sad.png'
+         MouseArea { anchors.fill: parent; onPressed: reset() }
+     }
+     Text {
+         anchors.centerIn: parent; width: parent.width - 20
+         horizontalAlignment: Text.AlignHCenter
+         wrapMode: Text.WordWrap
+         text: "Minehunt demo has to be compiled to run.\n\nPlease see README."
+         color: "white"; font.bold: true; font.pixelSize: 14
+         visible: tiles == undefined
+     }
+ }
index 0000000,f183c4b..164f47f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,147 +1,147 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.XmlListModel 2.0
+ Component {
+     id: albumDelegate
+     Package {
+         Item {
+             Package.name: 'browser'
+             GridView {
+                 id: photosGridView; model: visualModel.parts.grid; width: mainWindow.width; height: mainWindow.height - 21
+                 x: 0; y: 21; cellWidth: 160; cellHeight: 153; interactive: false
+                 onCurrentIndexChanged: photosListView.positionViewAtIndex(currentIndex, ListView.Contain)
+             }
+         }
+         Item {
+             Package.name: 'fullscreen'
+             ListView {
+                 id: photosListView; model: visualModel.parts.list; orientation: Qt.Horizontal
+                 width: mainWindow.width; height: mainWindow.height; interactive: false
+                 onCurrentIndexChanged: photosGridView.positionViewAtIndex(currentIndex, GridView.Contain)
+                 highlightRangeMode: ListView.StrictlyEnforceRange; snapMode: ListView.SnapOneItem
+             }
+         }
+         Item {
+             Package.name: 'album'
+             id: albumWrapper; width: 210; height: 220
+             VisualDataModel {
+                 id: visualModel; delegate: PhotoDelegate { }
+                 model: RssModel { id: rssModel; tags: tag }
+             }
+             BusyIndicator {
+                 id: busyIndicator
+                 anchors { centerIn: parent; verticalCenterOffset: -20 }
+                 on: rssModel.status != XmlListModel.Ready
+             }
+             PathView {
+                 id: photosPathView; model: visualModel.parts.stack; pathItemCount: 5
+                 visible: !busyIndicator.visible
+                 anchors.centerIn: parent; anchors.verticalCenterOffset: -30
+                 path: Path {
+                     PathAttribute { name: 'z'; value: 9999.0 }
+                     PathLine { x: 1; y: 1 }
+                     PathAttribute { name: 'z'; value: 0.0 }
+                 }
+             }
+             MouseArea {
+                 anchors.fill: parent
+                 onClicked: mainWindow.editMode ? photosModel.remove(index) : albumWrapper.state = 'inGrid'
+             }
+             Tag {
+                 anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: 10 }
+                 frontLabel: tag; backLabel: qsTr("Remove"); flipped: mainWindow.editMode
+                 onTagChanged: rssModel.tags = tag
+                 onBackClicked: if (mainWindow.editMode) photosModel.remove(index);
+             }
+             states: [
+             State {
+                 name: 'inGrid'
+                 PropertyChanges { target: photosGridView; interactive: true }
+                 PropertyChanges { target: albumsShade; opacity: 1 }
+                 PropertyChanges { target: backButton; onClicked: albumWrapper.state = ''; y: 6 }
+             },
+             State {
+                 name: 'fullscreen'; extend: 'inGrid'
+                 PropertyChanges { target: photosGridView; interactive: false }
+                 PropertyChanges { target: photosListView; interactive: true }
+                 PropertyChanges { target: photosShade; opacity: 1 }
+                 PropertyChanges { target: backButton; y: -backButton.height - 8 }
+             }
+             ]
+             GridView.onAdd: NumberAnimation {
+                 target: albumWrapper; properties: "scale"; from: 0.0; to: 1.0; easing.type: Easing.OutQuad
+             }
+             GridView.onRemove: SequentialAnimation {
+                 PropertyAction { target: albumWrapper; property: "GridView.delayRemove"; value: true }
+                 NumberAnimation { target: albumWrapper; property: "scale"; from: 1.0; to: 0.0; easing.type: Easing.OutQuad }
+                 PropertyAction { target: albumWrapper; property: "GridView.delayRemove"; value: false }
+             }
+             transitions: [
+             Transition {
+                 from: '*'; to: 'inGrid'
+                 SequentialAnimation {
+                     NumberAnimation { properties: 'opacity'; duration: 250 }
+                     PauseAnimation { duration: 350 }
+                     NumberAnimation { target: backButton; properties: "y"; duration: 200; easing.type: Easing.OutQuad }
+                 }
+             },
+             Transition {
+                 from: 'inGrid'; to: '*'
+                 NumberAnimation { properties: "y,opacity"; easing.type: Easing.OutQuad; duration: 300 }
+             }
+             ]
+         }
+     }
+ }
index 0000000,2b1a75f..867c268
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,50 +1,50 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Image {
+     id: container
+     property bool on: false
+     source: "images/busy.png"; visible: container.on
+     NumberAnimation on rotation { running: container.on; from: 0; to: 360; loops: Animation.Infinite; duration: 1200 }
+ }
index 0000000,fcce969..8f4177c
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,72 +1,72 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: container
+     property alias label: labelText.text
+     property color tint: "transparent"
+     signal clicked
+     width: labelText.width + 70 ; height: labelText.height + 18
+     BorderImage {
+         anchors { fill: container; leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8 }
+         source: 'images/box-shadow.png'; smooth: true
+         border.left: 10; border.top: 10; border.right: 10; border.bottom: 10
+     }
+     Image { anchors.fill: parent; source: "images/cardboard.png"; smooth: true }
+     Rectangle {
+         anchors.fill: container; color: container.tint; visible: container.tint != ""
+         opacity: 0.25; smooth: true
+     }
+     Text { id: labelText; font.pixelSize: 15; anchors.centerIn: parent; smooth: true }
+     MouseArea {
+         anchors { fill: parent; leftMargin: -20; topMargin: -20; rightMargin: -20; bottomMargin: -20 }
+         onClicked: container.clicked()
+     }
+ }
index 0000000,5d84593..435ad26
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,86 +1,86 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: container
+     property string label
+     signal clicked
+     signal labelChanged(string label)
+     width: textInput.width + 70 ; height: textInput.height + 18
+     BorderImage {
+         anchors { fill: container; leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8 }
+         source: 'images/box-shadow.png'; smooth: true
+         border.left: 10; border.top: 10; border.right: 10; border.bottom: 10
+     }
+     Image { anchors.fill: parent; source: "images/cardboard.png"; smooth: true }
+     TextInput {
+         id: textInput; text: label; font.pixelSize: 15; anchors.centerIn: parent; smooth: true
+         Keys.onReturnPressed: {
+             container.labelChanged(textInput.text)
+             container.focus = true
+         }
+         Keys.onEnterPressed: {
+             container.labelChanged(textInput.text)
+             container.focus = true
+         }
+         Keys.onEscapePressed: {
+             textInput.text = container.label
+             container.focus = true
+         }
+     }
+     Rectangle {
+         anchors.fill: container; border.color: "steelblue"; border.width: 4
+         color: "transparent"; visible: textInput.focus; smooth: true
+     }
+     MouseArea {
+         anchors { fill: parent; leftMargin: -20; topMargin: -20; rightMargin: -20; bottomMargin: -20 }
+         onClicked: { textInput.forceActiveFocus(); textInput.openSoftwareInputPanel(); }
+     }
+ }
index 0000000,b972c93..5d4e5ae
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,188 +1,188 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import "script/script.js" as Script
+ Package {
+     Item { id: stackItem; Package.name: 'stack'; width: 160; height: 153; z: stackItem.PathView.z }
+     Item { id: listItem; Package.name: 'list'; width: mainWindow.width + 40; height: 153 }
+     Item { id: gridItem; Package.name: 'grid'; width: 160; height: 153 }
+     Item {
+         width: 160; height: 153
+         Item {
+             id: photoWrapper
+             property double randomAngle: Math.random() * (2 * 6 + 1) - 6
+             property double randomAngle2: Math.random() * (2 * 6 + 1) - 6
+             x: 0; y: 0; width: 140; height: 133
+             z: stackItem.PathView.z; rotation: photoWrapper.randomAngle
+             BorderImage {
+                 anchors {
+                     fill: originalImage.status == Image.Ready ? border : placeHolder
+                     leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8
+                 }
+                 source: 'images/box-shadow.png'; smooth: true
+                 border.left: 10; border.top: 10; border.right: 10; border.bottom: 10
+             }
+             Rectangle {
+                 id: placeHolder
+                 property int w: Script.getWidth(content)
+                 property int h: Script.getHeight(content)
+                 property double s: Script.calculateScale(w, h, photoWrapper.width)
+                 color: 'white'; anchors.centerIn: parent; smooth: true
+                 width:  w * s; height: h * s; visible: originalImage.status != Image.Ready
+                 Rectangle {
+                     color: "#878787"; smooth: true
+                     anchors { fill: parent; topMargin: 3; bottomMargin: 3; leftMargin: 3; rightMargin: 3 }
+                 }
+             }
+             Rectangle {
+                 id: border; color: 'white'; anchors.centerIn: parent; smooth: true
+                 width: originalImage.paintedWidth + 6; height: originalImage.paintedHeight + 6
+                 visible: !placeHolder.visible
+             }
+             BusyIndicator { anchors.centerIn: parent; on: originalImage.status != Image.Ready }
+             Image {
+                 id: originalImage; smooth: true; source: "http://" + Script.getImagePath(content); cache: false
+                 fillMode: Image.PreserveAspectFit; width: photoWrapper.width; height: photoWrapper.height
+             }
+             Image {
+                 id: hqImage; smooth: true; source: ""; visible: false; cache: false
+                 fillMode: Image.PreserveAspectFit; width: photoWrapper.width; height: photoWrapper.height
+             }
+             Binding {
+                 target: mainWindow; property: "downloadProgress"; value: hqImage.progress
+                 when: listItem.ListView.isCurrentItem
+             }
+             Binding {
+                 target: mainWindow; property: "imageLoading"
+                 value: (hqImage.status == Image.Loading) ? 1 : 0; when: listItem.ListView.isCurrentItem
+             }
+             MouseArea {
+                 width: originalImage.paintedWidth; height: originalImage.paintedHeight; anchors.centerIn: originalImage
+                 onClicked: {
+                     if (albumWrapper.state == 'inGrid') {
+                         gridItem.GridView.view.currentIndex = index;
+                         albumWrapper.state = 'fullscreen'
+                     } else {
+                         gridItem.GridView.view.currentIndex = index;
+                         albumWrapper.state = 'inGrid'
+                     }
+                 }
+             }
+             states: [
+             State {
+                 name: 'stacked'; when: albumWrapper.state == ''
+                 ParentChange { target: photoWrapper; parent: stackItem; x: 10; y: 10 }
+                 PropertyChanges { target: photoWrapper; opacity: stackItem.PathView.onPath ? 1.0 : 0.0 }
+             },
+             State {
+                 name: 'inGrid'; when: albumWrapper.state == 'inGrid'
+                 ParentChange { target: photoWrapper; parent: gridItem; x: 10; y: 10; rotation: photoWrapper.randomAngle2 }
+             },
+             State {
+                 name: 'fullscreen'; when: albumWrapper.state == 'fullscreen'
+                 ParentChange {
+                     target: photoWrapper; parent: listItem; x: 0; y: 0; rotation: 0
+                     width: mainWindow.width; height: mainWindow.height
+                 }
+                 PropertyChanges { target: border; opacity: 0 }
+                 PropertyChanges { target: hqImage; source: listItem.ListView.isCurrentItem ? hq : ""; visible: true }
+             }
+             ]
+             transitions: [
+             Transition {
+                 from: 'stacked'; to: 'inGrid'
+                 SequentialAnimation {
+                     PauseAnimation { duration: 10 * index }
+                     ParentAnimation {
+                         target: photoWrapper; via: foreground
+                         NumberAnimation {
+                             target: photoWrapper; properties: 'x,y,rotation,opacity'; duration: 600; easing.type: 'OutQuart'
+                         }
+                     }
+                 }
+             },
+             Transition {
+                 from: 'inGrid'; to: 'stacked'
+                 ParentAnimation {
+                     target: photoWrapper; via: foreground
+                     NumberAnimation { properties: 'x,y,rotation,opacity'; duration: 600; easing.type: 'OutQuart' }
+                 }
+             },
+             Transition {
+                 from: 'inGrid'; to: 'fullscreen'
+                 SequentialAnimation {
+                     PauseAnimation { duration: gridItem.GridView.isCurrentItem ? 0 : 600 }
+                     ParentAnimation {
+                         target: photoWrapper; via: foreground
+                         NumberAnimation {
+                             targets: [ photoWrapper, border ]
+                             properties: 'x,y,width,height,opacity,rotation'
+                             duration: gridItem.GridView.isCurrentItem ? 600 : 1; easing.type: 'OutQuart'
+                         }
+                     }
+                 }
+             },
+             Transition {
+                 from: 'fullscreen'; to: 'inGrid'
+                 ParentAnimation {
+                     target: photoWrapper; via: foreground
+                     NumberAnimation {
+                         targets: [ photoWrapper, border ]
+                         properties: 'x,y,width,height,rotation,opacity'
+                         duration: gridItem.GridView.isCurrentItem ? 600 : 1; easing.type: 'OutQuart'
+                     }
+                 }
+             }
+             ]
+         }
+     }
+ }
index 0000000,43c936e..58beef5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,57 +1,57 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: container
+     property real progress: 0
+     Behavior on opacity { NumberAnimation { duration: 600 } }
+     Rectangle { anchors.fill: parent; color: "black"; opacity: 0.5 }
+     Rectangle {
+         id: fill; color: "white"; height: container.height
+         width: container.width * container.progress
+     }
+ }
index 0000000,ab81892..1598977
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,57 +1,57 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.XmlListModel 2.0
+ XmlListModel {
+     property string tags : ""
+     function encodeTags(x) { return encodeURIComponent(x.replace(' ',',')); }
+     source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+encodeTags(tags)+"&" : "")
+     query: "/feed/entry"
+     namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom';"
+     XmlRole { name: "title"; query: "title/string()" }
+     XmlRole { name: "content"; query: "content/string()" }
+     XmlRole { name: "hq"; query: "link[@rel='enclosure']/@href/string()" }
+ }
index 0000000,2b546a3..ed4a248
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,91 +1,91 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Flipable {
+     id: flipable
+     property alias frontLabel: frontButton.label
+     property alias backLabel: backButton.label
+     property int angle: 0
+     property int randomAngle: Math.random() * (2 * 6 + 1) - 6
+     property bool flipped: false
+     signal frontClicked
+     signal backClicked
+     signal tagChanged(string tag)
+     front: EditableButton {
+         id: frontButton; rotation: flipable.randomAngle
+         anchors { centerIn: parent; verticalCenterOffset: -20 }
+         onClicked: flipable.frontClicked()
+         onLabelChanged: flipable.tagChanged(label)
+     }
+     back: Button {
+         id: backButton; tint: "red"; rotation: flipable.randomAngle
+         anchors { centerIn: parent; verticalCenterOffset: -20 }
+         onClicked: flipable.backClicked()
+     }
+     transform: Rotation {
+         origin.x: flipable.width / 2; origin.y: flipable.height / 2
+         axis.x: 0; axis.y: 1; axis.z: 0
+         angle: flipable.angle
+     }
+     states: State {
+         name: "back"; when: flipable.flipped
+         PropertyChanges { target: flipable; angle: 180 }
+     }
+     transitions: Transition {
+         ParallelAnimation {
+             NumberAnimation { properties: "angle"; duration: 400 }
+             SequentialAnimation {
+                 NumberAnimation { target: flipable; property: "scale"; to: 0.8; duration: 200 }
+                 NumberAnimation { target: flipable; property: "scale"; to: 1.0; duration: 200 }
+             }
+         }
+     }
+ }
index 0000000,9184388..208720b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,110 +1,110 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import "PhotoViewerCore"
+ Rectangle {
+     id: mainWindow
+     property real downloadProgress: 0
+     property bool imageLoading: false
+     property bool editMode: false
+     width: 800; height: 480; color: "#d5d6d8"
+     ListModel {
+         id: photosModel
+         ListElement { tag: "Flowers" }
+         ListElement { tag: "Wildlife" }
+         ListElement { tag: "Prague" }
+     }
+     VisualDataModel { id: albumVisualModel; model: photosModel; delegate: AlbumDelegate {} }
+     GridView {
+         id: albumView; width: parent.width; height: parent.height; cellWidth: 210; cellHeight: 220
+         model: albumVisualModel.parts.album; visible: albumsShade.opacity != 1.0
+     }
+     Column {
+         spacing: 20; anchors { bottom: parent.bottom; right: parent.right; rightMargin: 20; bottomMargin: 20 }
+         Button {
+             id: newButton; label: qsTr("Add"); rotation: 3
+             anchors.horizontalCenter: parent.horizontalCenter
+             onClicked: {
+                 mainWindow.editMode = false
+                 photosModel.append( { tag: "" } )
+                 albumView.positionViewAtIndex(albumView.count - 1, GridView.Contain)
+             }
+         }
+         Button {
+             id: deleteButton; label: qsTr("Edit"); rotation: -2;
+             onClicked: mainWindow.editMode = !mainWindow.editMode
+             anchors.horizontalCenter: parent.horizontalCenter
+         }
+         Button {
+             id: quitButton; label: qsTr("Quit"); rotation: -2;
+             onClicked: Qt.quit()
+             anchors.horizontalCenter: parent.horizontalCenter
+         }
+     }
+     Rectangle {
+         id: albumsShade; color: mainWindow.color
+         width: parent.width; height: parent.height; opacity: 0.0
+     }
+     ListView { anchors.fill: parent; model: albumVisualModel.parts.browser; interactive: false }
+     Button { id: backButton; label: qsTr("Back"); rotation: 3; x: parent.width - backButton.width - 6; y: -backButton.height - 8 }
+     Rectangle { id: photosShade; color: 'black'; width: parent.width; height: parent.height; opacity: 0; visible: opacity != 0.0 }
+     ListView { anchors.fill: parent; model: albumVisualModel.parts.fullscreen; interactive: false }
+     Item { id: foreground; anchors.fill: parent }
+     ProgressBar {
+         progress: mainWindow.downloadProgress; width: parent.width; height: 4
+         anchors.bottom: parent.bottom; opacity: mainWindow.imageLoading; visible: opacity != 0.0
+     }
+ }
index 0000000,4ac30d0..10c50d4
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,133 +1,133 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     id: container
+     property variant target: {"y": -90, "x":12}
+     property Item targetObj: container
+     property Item hardpoint: container
+     property ParticleSystem system
+     property int blasts: 16
+     property int bonusBlasts: 12
+     property bool show: true
+     width: 24
+     height: 24
+     Emitter {
+         id: visualization
+         group: "blaster"
+         system: container.system
+         enabled: show
+         anchors.fill: parent
+         shape: EllipseShape {}
+         speed: TargetDirection { targetX: width/2; targetY: width/2; magnitude: -1; proportionalMagnitude: true}
+         lifeSpan: 1000
+         emitRate: 64 
+         size: 24
+         sizeVariation: 24
+         endSize: 0
+     }
+     property int blastsLeft: 0
+     function fireAt(targetArg, container) {
+         target = container.mapFromItem(targetArg, targetArg.width/2, targetArg.height/2);
+         targetObj = targetArg;
+         hardpoint = container;
+         blastsLeft = blasts;
+         rofTimer.repeat = true;
+         rofTimer.start();
+     }
+     Timer {
+         id: rofTimer
+         interval: 30;//Has to be greater than 1 frame or they stack up
+         running: false
+         repeat: false
+         onTriggered: {
+             if (targetObj.hp <= 0)
+                 return;
+             //TODO: calculate hit and damage at target, which must be a Ship
+             var hit;
+             if (blastsLeft >= bonusBlasts)
+                 hit = Math.random() > targetObj.dodge;
+             else
+                 hit = false; //purely aesthetic shots, because the damage isn't that fine grained
+             if (hit == true) {
+                 switch (targetObj.shipType) {
+                 case 1: hardpoint.damageDealt += 4; break;
+                 case 2: hardpoint.damageDealt += 5; break;
+                 case 3: hardpoint.damageDealt += 1; break;
+                 default: hardpoint.damageDealt += 100;
+                 }
+             }
+             blastVector.targetX = target.x;
+             blastVector.targetY = target.y;
+             if (!hit) {//TODO: Actual targetVariation
+                 blastVector.targetX += (128 * Math.random() - 64);
+                 blastVector.targetY += (128 * Math.random() - 64);
+             }
+             emitter.burst(1);
+             blastsLeft--;
+             if (!blastsLeft)
+                 rofTimer.repeat = false;
+         }
+     }
+     Emitter {
+         id: emitter
+         group: "blaster"
+         enabled: false
+         system: container.system
+         anchors.centerIn: parent
+         lifeSpan: 1000
+         emitRate: 16
+         maximumEmitted: blasts
+         size: 24
+         endSize:16
+         sizeVariation: 8
+         speed: TargetDirection {
+             id: blastVector
+             targetX: target.x; targetY: target.y; magnitude: 1.1; proportionalMagnitude: true
+         }
+     }
+ }
index 0000000,405b993..992be29
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,66 +1,66 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ //TODO: Add particles to this component too
+ Rectangle {
+     id: container
+     property alias text: txt.text
+     signal clicked
+     //color: "lightsteelblue"
+     gradient: Gradient {
+         GradientStop { position: 0.0; color: "lightsteelblue" }
+         GradientStop { position: 1.0; color: "steelblue" }
+     }
+     height: 64
+     radius: 16
+     width: 128
+     Text {
+         id: txt
+         anchors.centerIn: parent
+         font.pixelSize: 24
+         color: "white"
+     }
+     MouseArea {
+         anchors.fill: parent
+         onClicked: container.clicked()
+     }
+ }
index 0000000,c4aa412..48eb9d1
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,97 +1,97 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     id: container
+     property variant target: {"y": -90, "x":12}
+     property ParticleSystem system
+     property bool show: true
+     width: 24
+     height: 24
+     Emitter {
+         id: visualization
+         group: "cannon"
+         enabled: container.show
+         system: container.system
+         anchors.centerIn: parent
+         lifeSpan: 2000
+         emitRate: 1
+         size: 4
+         endSize: 0
+     }
+     function fireAt(targetArg, hardpoint) {
+         target = container.mapFromItem(targetArg, targetArg.width/2, targetArg.height/2);
+         if (container.hp <= 0 || targetArg.hp <= 0)
+             return;
+         //TODO: calculate hit and damage at target, which must be a Ship
+         var hit = Math.random() > targetArg.dodge
+         if (hit) {
+             switch (targetArg.shipType) {
+             case 1: hardpoint.damageDealt += 8; break;
+             case 2: hardpoint.damageDealt += 10; break;
+             case 3: hardpoint.damageDealt += 16; break;
+             default: hardpoint.damageDealt += 1000;
+             }
+         }
+         emitter.burst(1);
+     }
+     Emitter {
+         id: emitter
+         group: "cannon"
+         enabled: false
+         system: container.system
+         anchors.centerIn: parent
+         lifeSpan: 1000
+         emitRate: 1
+         size: 8
+         endSize: 4
+         speed: TargetDirection {
+             id: blastVector
+             targetX: target.x; targetY: target.y; magnitude: 1.1; proportionalMagnitude: true
+         }
+     }
+ }
index 0000000,a678bc9..6e21101
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,105 +1,105 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     id: container
+     width: 360
+     height: 160
+     property ParticleSystem system
+     Ship {
+         id: nully
+         system: system
+     }
+     property Item target: nully
+     /*
+     Component.onCompleted: {
+         container.target.shipType = 1
+         container.target.gunType = 1
+     }
+     */
+     Row {
+         anchors.horizontalCenter: parent.horizontalCenter
+         height: parent.height
+         spacing: 8
+         Button {
+             width: 80
+             height: 80
+             anchors.verticalCenter: parent.verticalCenter
+             text: "Cycle\nShip"
+             onClicked: {
+                 var nextVal = container.target.shipType;
+                 if(nextVal == 3)
+                     nextVal = 1;
+                 else 
+                     nextVal++;
+                 container.target.shipType = nextVal;
+             }
+         }
+         Item {
+             width: 128
+             height: 128
+             anchors.verticalCenter: parent.verticalCenter
+             Ship {
+                 hp: 20
+                 anchors.centerIn: parent
+                 shipType: container.target.shipType
+                 gunType: container.target.gunType
+                 system: container.system
+             }
+         }
+         Button {
+             width: 80
+             height: 80
+             anchors.verticalCenter: parent.verticalCenter
+             text: "Cycle\nGun"
+             onClicked: {
+                 var nextVal = container.target.gunType;
+                 if(nextVal == 3)
+                     nextVal = 1;
+                 else 
+                     nextVal++;
+                 container.target.gunType = nextVal;
+             }
+         }
+     }
+ }
index 0000000,c689879..c469eb4
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,146 +1,146 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     id: container
+     property int maxHP: 100
+     property int hp: maxHP
+     property real initialDodge: 0.01
+     property real dodge: initialDodge
+     onHpChanged: if(hp <= 0) target = container;
+     property ParticleSystem system//TODO: Ship abstraction
+     property Item target: container
+     property string shipParticle: "default"//Per team colors?
+     property int gunType: 0
+     width: 128
+     height: 128
+     Emitter {
+         //TODO: Cooler would be an 'orbiting' affector
+         //TODO: On the subject, opacity and size should be grouped type 'overLife' if we can cram that in the particles
+         system: container.system
+         group: container.shipParticle
+         anchors.centerIn: parent
+         width: 64
+         height: 64
+         shape: EllipseShape {}
+         emitRate: hp > 0 ?  hp * 1 + 20 : 0 
+         lifeSpan: 2400
+         maximumEmitted: (maxHP * 1 + 20)*2.4
+         size: 48
+         sizeVariation: 16
+         endSize: 16
+         speed: AngleDirection {angleVariation:360; magnitudeVariation: 32}
+     }
+     Emitter {
+         system: container.system
+         group: "cruiserArmor"
+         anchors.fill: parent
+         shape: EllipseShape { fill: false }
+         enabled: hp>0
+         
+         emitRate: 16
+         lifeSpan: 2000
+         size: 48
+         sizeVariation: 24
+         SpriteGoal {
+             id: destructor
+             system: container.system
+             enabled: container.hp <=0
+             anchors.fill: parent
+             groups: ["cruiserArmor"]
+             goalState: "death"
+ //            jump: true
+             once: true
+         }
+     }
+     Timer {
+         id: fireControl
+         property int next: Math.floor(Math.random() * 3) + 1
+         interval: 800
+         running: root.readySetGo
+         repeat: true
+         onTriggered: {
+             if (next == 1) {
+                 gun1.fireAt(container.target);
+                 next = Math.floor(Math.random() * 3) + 1;
+             } else if (next == 2) {
+                 gun2.fireAt(container.target);
+                 next = Math.floor(Math.random() * 3) + 1;
+             } else if (next == 3) {
+                 gun3.fireAt(container.target);
+                 next = Math.floor(Math.random() * 3) + 1;
+             }
+         }
+     }
+     Hardpoint {//TODO: Hardpoint abstraction
+         x: 112 - 12 - 8*2
+         y: 128 - 12 - 12*2
+         id: gun1
+         system: container.system
+         show: hp > 0
+         hardpointType: gunType
+     }
+     Hardpoint {
+         x: 64 - 12
+         y: 0 - 12 + 12*2
+         id: gun2
+         system: container.system
+         show: hp > 0
+         hardpointType: gunType
+     }
+     Hardpoint {
+         x: 16 - 12 + 8*2
+         y: 128 - 12 - 12*2
+         id: gun3
+         system: container.system
+         show: hp > 0
+         hardpointType: gunType
+     }
+ }
index 0000000,de099be..92c63b8
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,114 +1,114 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     id: container
+     property int maxHP: 100
+     property int hp: maxHP
+     property real initialDodge: 0.2
+     property real dodge: initialDodge
+     onHpChanged: if(hp <= 0) target = container;
+     property ParticleSystem system//TODO: Ship abstraction
+     property Item target: container
+     property string shipParticle: "default"//Per team colors?
+     property int gunType: 0
+     width: 128
+     height: 128
+     Emitter {
+         system: container.system
+         group: "frigateShield"
+         anchors.centerIn: parent
+         size: 92
+         emitRate: 1
+         lifeSpan: 4800
+         enabled: hp > 0
+     }
+     Emitter {
+         system: container.system
+         group: container.shipParticle
+         anchors.centerIn: parent
+         width: 64 
+         height: 16
+         shape: EllipseShape {}
+         size: 16
+         sizeVariation: 8
+         endSize: 8
+         emitRate: hp > 0 ?  hp * 1 + 20 : 0 
+         lifeSpan: 1200
+         maximumEmitted: (maxHP * 1 + 20)*2
+     }
+     Timer {
+         id: fireControl
+         property int next: Math.floor(Math.random() * 2) + 1
+         interval: 800
+         running: root.readySetGo
+         repeat: true
+         onTriggered: {
+             if (next == 1) {
+                 gun1.fireAt(container.target);
+                 next = Math.floor(Math.random() * 2) + 1;
+             } else if (next == 2) {
+                 gun2.fireAt(container.target);
+                 next = Math.floor(Math.random() * 2) + 1;
+             }
+         }
+     }
+     Hardpoint {
+         x: 128 - 32 - 12
+         y: 64 - 12
+         id: gun1
+         system: container.system
+         show: hp > 0
+         hardpointType: gunType
+     }
+     Hardpoint {
+         x: 0 + 32 - 12
+         y: 64 - 12
+         id: gun2
+         system: container.system
+         show: hp > 0
+         hardpointType: gunType
+     }
+ }
index 0000000,5c7fb55..9e60570
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,114 +1,114 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     id: container
+     //ReflectiveProperties
+     //TransferredProperties
+     property variant target: {"y": -90, "x":12}
+     property ParticleSystem system
+     property bool show: true
+     property int hardpointType: 0 //default is pea shooter - always bad.
+     property Item targetObj: null
+     property int damageDealt: 0
+     onDamageDealtChanged: dealDamageTimer.start();
+     Timer {
+         id: dealDamageTimer
+         interval: 16
+         running: false
+         repeat: false
+         onTriggered: {targetObj.hp -= damageDealt; damageDealt = 0;}
+     }
+     width: 24
+     height: 24
+     function fireAt(targetArg) {//Each implement own
+         if (targetArg != null) {
+             hardpointLoader.item.fireAt(targetArg, container);
+             targetObj = targetArg;
+         }
+     }
+     Loader {
+         id: hardpointLoader
+         sourceComponent:  {
+             switch (hardpointType) {
+             case 1: laserComponent; break;
+             case 2: blasterComponent; break;
+             case 3: cannonComponent; break;
+             default: emptyComponent;
+             }
+         }
+     }
+     Component {
+         id: laserComponent
+         LaserHardpoint {
+             target: container.target
+             system: container.system
+             show: container.show
+         }
+     }
+     Component {
+         id: blasterComponent
+         BlasterHardpoint {
+             target: container.target
+             system: container.system
+             show: container.show
+         }
+     }
+     Component {
+         id: cannonComponent
+         CannonHardpoint {
+             target: container.target
+             system: container.system
+             show: container.show
+         }
+     }
+     Component {
+         id: emptyComponent
+         Item {
+             function fireAt(obj) {
+                 console.log("Firing null weapon. It hurts.");
+             }
+         }
+     }
+ }
index 0000000,9297f86..db70c6e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,268 +1,268 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ SequentialLoader {
+     id: hLdr
+     signal exitDesired
+     Component.onCompleted: advance();
+     ParticleSystem { id: helpSystem }
+     PlasmaPatrolParticles { sys: helpSystem }
+     pages: [
+         Component {Item {
+             id: story
+             Text {
+                 color: "white"
+                 text: "Story"
+                 font.pixelSize: 48
+             }
+             /*
+             Flickable {
+                 y: 60
+                 width: 360
+                 height: 500
+                 contentHeight: txt1.height
+                 contentWidth: 360//TODO: Less magic numbers?
+                 */
+                 Text {
+                     id: txt1
+                     color: "white"
+                     y: 60
+                     font.pixelSize: 18
+                     text: "
+ In a remote nebula, a race of energy beings formed and lived prosperous lives for millenia. Until the schism - when they became constantly at each other's energy-throats. War soon followed, crippling both sides, until a truce was formed. But while governments knew the desparate need for peace, the soldiers in the ion-field were still filled with rampant bloodlust. On the border, patrols are constantly engaging in minor skirmishes whenever they cross paths. 
+ You must select one such patrol unit for the border, heading into an inevitable skirmish, in Plasma Patrol: the game of energy being spaceship combat!
+                     "
+                     width: 360
+                     wrapMode: Text.WordWrap
+                 }
+            // }
+             Button {
+                 x: 20
+                 y: 560
+                 height: 40
+                 width: 120
+                 text: "Next"
+                 onClicked: hLdr.advance();
+             }
+             Button {
+                 x: 220
+                 y: 560
+                 height: 40
+                 width: 120
+                 text: "Menu"
+                 onClicked: hLdr.exitDesired();
+             }
+         }},
+         Component {Item {
+             id: ships
+             Text {
+                 color: "white"
+                 text: "Vessels"
+                 font.pixelSize: 48
+             }
+             Column {
+                 spacing: 16
+                 y: 60
+                 Row {
+                     height: 128
+                     Sloop {
+                         system: helpSystem
+                     }
+                     Text {
+                         text: "The nimble sloop"
+                         color: "white"
+                         font.pixelSize: 18
+                     }
+                 }
+                 Row {
+                     height: 128
+                     Frigate {
+                         system: helpSystem
+                     }
+                     Text {
+                         text: "The versitile shield frigate"
+                         color: "white"
+                         font.pixelSize: 18
+                     }
+                 }
+                 Row {
+                     height: 128
+                     Cruiser {
+                         system: helpSystem
+                     }
+                     Text {
+                         text: "The armored cruiser"
+                         color: "white"
+                         font.pixelSize: 18
+                     }
+                 }
+             }
+             Button {
+                 x: 20
+                 y: 560
+                 height: 40
+                 width: 120
+                 text: "Next"
+                 onClicked: hLdr.advance();
+             }
+             Button {
+                 x: 220
+                 y: 560
+                 height: 40
+                 width: 120
+                 text: "Menu"
+                 onClicked: hLdr.exitDesired();
+             }
+         }},
+         Component {Item {
+             id: guns
+             Text {
+                 color: "white"
+                 text: "Hardpoints"
+                 font.pixelSize: 48
+             }
+             Column {
+                 spacing: 16
+                 y: 60
+                 Row {
+                     height: 128
+                     LaserHardpoint {
+                         system: helpSystem
+                     }
+                     Text {
+                         text: "The laser hardpoint almost always hits the target, even the nimble sloop, but loses much of its potency against the frigate's shields"
+                         width: 332
+                         wrapMode: Text.WordWrap
+                         color: "white"
+                         font.pixelSize: 18
+                     }
+                 }
+                 Row {
+                     height: 128
+                     BlasterHardpoint {
+                         system: helpSystem
+                     }
+                     Text {
+                         text: "The blaster passes right through the frigate's shields but loses much of its impact against the armor of the cruiser"
+                         width: 332
+                         wrapMode: Text.WordWrap
+                         color: "white"
+                         font.pixelSize: 18
+                     }
+                 }
+                 Row {
+                     height: 128
+                     CannonHardpoint {
+                         system: helpSystem
+                     }
+                     Text {
+                         text: "The cannon has poor accuracy, often missing the nimble sloop, but can punch right through the armor of the cruiser"
+                         width: 332
+                         wrapMode: Text.WordWrap
+                         color: "white"
+                         font.pixelSize: 18
+                     }
+                 }
+             }
+             Button {
+                 x: 20
+                 y: 560
+                 height: 40
+                 width: 120
+                 text: "Next"
+                 onClicked: hLdr.advance();
+             }
+             Button {
+                 x: 220
+                 y: 560
+                 height: 40
+                 width: 120
+                 text: "Menu"
+                 onClicked: hLdr.exitDesired();
+             }
+         }},
+         Component {Item {
+             id: strategy
+             Text {
+                 color: "white"
+                 text: "Strategy"
+                 font.pixelSize: 48
+             }
+             Flickable {
+                 y: 60
+                 width: 360
+                 height: 500
+                 contentHeight: txt1.height
+                 contentWidth: 360//TODO: Less magic numbers?
+                 Text {
+                     id: txt1
+                     color: "white"
+                     font.pixelSize: 18
+                     text: "
+ Basic Strategy: Good luck, have fun - don't die.
+ More to come after thorough playtesting.
+                     "
+                     width: 360
+                     wrapMode: Text.WordWrap
+                 }
+             }
+             Button {
+                 x: 20
+                 y: 560
+                 height: 40
+                 width: 120
+                 text: "Story"
+                 onClicked: {hLdr.at=0; hLdr.advance();}
+             }
+             Button {
+                 x: 220
+                 y: 560
+                 height: 40
+                 width: 120
+                 text: "Menu"
+                 onClicked: hLdr.exitDesired();
+             }
+         }}
+     ]
+ }
index 0000000,87ac3e9..a7baed6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,108 +1,108 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     id: container
+     property variant target: {"y": -90, "x":12}
+     property ParticleSystem system
+     property bool show: true
+     width: 24
+     height: 24
+     Emitter {
+         id: visualization
+         group: "laser"
+         system: container.system
+         anchors.fill: parent
+         enabled: container.show
+         shape: EllipseShape {}
+         speed: TargetDirection { targetX: width/2; targetY: width/2; magnitude: -1; proportionalMagnitude: true }
+         lifeSpan: 1000
+         emitRate: 64
+         size: 24
+         sizeVariation: 8
+         endSize: 8
+     }
+     function fireAt(targetArg, hardpoint) {
+         if (targetArg.hp <= 0)
+             return;
+         //TODO: calculate hit and damage at target, which must be a Ship
+         var offset = 0;
+         if (Math.random() < 0.99) {
+             switch (targetArg.shipType) {
+             case 1: hardpoint.damageDealt += 16; break;
+             case 2: hardpoint.damageDealt += 4; break;
+             case 3: hardpoint.damageDealt += 8; break;
+             default: hardpoint.damageDealt += 500; //Really effective against unregistered vessels
+             }
+         } else {//Misses with Lasers are really rare
+             offset = Math.random() * 100;
+         }
+         target = container.mapFromItem(targetArg, offset + targetArg.width/2, offset + targetArg.height/2);
+         emitter.pulse(100);
+  //       console.log("Fire box: " +  Math.min(container.width/2, target.x) + "," + Math.min(container.height/2, target.y) + " " + (Math.max(container.width/2, target.x) - Math.min(container.width/2, target.x)) + "," + (Math.max(container.height/2, target.y) - Math.min(container.height/2, target.y)));
+     }
+     Emitter {
+         id: emitter
+         group: "laser"
+         enabled: false
+         system: container.system
+         x: Math.min(container.width/2, target.x);
+         width: Math.max(container.width/2, target.x) - x;
+         y: Math.min(container.height/2, target.y);
+         height: Math.max(container.height/2, target.y) - y;
+         shape: LineShape {
+             mirrored: (emitter.y < 0 || emitter.x < 0) && !(emitter.y < 0 && emitter.x < 0 )//I just want XOR
+         }
+         lifeSpan: 1000
+         emitRate: 8000
+         maximumEmitted: 800
+         size: 16
+         endSize: 0
+         speed: PointDirection {xVariation: 4; yVariation: 4}
+     }
+ }
index 0000000,1d856b5..e1924c3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,173 +1,173 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     property ParticleSystem sys
+     ImageParticle {
+         system: sys
+         groups: ["default"]
+         source: "pics/blur-circle3.png"
+         color: "#003A3A3A"
+         colorVariation: 0.1
+         z: 0
+     }
+     ImageParticle {
+         system: sys
+         groups: ["redTeam"]
+         source: "pics/blur-circle3.png"
+         color: "#0028060A"
+         colorVariation: 0.1
+         z: 0
+     }
+     ImageParticle {
+         system: sys
+         groups: ["greenTeam"]
+         source: "pics/blur-circle3.png"
+         color: "#0006280A"
+         colorVariation: 0.1
+        z: 0
+     }
+     ImageParticle {
+         system: sys
+         groups: ["blaster"]
+         source: "pics/star2.png"
+         //color: "#0F282406"
+         color: "#0F484416"
+         colorVariation: 0.2
+         z: 2
+     }
+     ImageParticle {
+         system: sys
+         groups: ["laser"]
+         source: "pics/star3.png"
+         //color: "#00123F68"
+         color: "#00428FF8"
+         colorVariation: 0.2
+         z: 2
+     }
+     ImageParticle {
+         system: sys
+         groups: ["cannon"]
+         source: "pics/particle.png"
+         color: "#80FFAAFF"
+         colorVariation: 0.1
+         z: 2
+     }
+     ImageParticle {
+         system: sys
+         groups: ["cannonCore"]
+         source: "pics/particle.png"
+         color: "#00666666"
+         colorVariation: 0.8
+         z: 1
+     }
+     ImageParticle {
+         system: sys
+         groups: ["cannonWake"]
+         source: "pics/star.png"
+         color: "#00CCCCCC"
+         colorVariation: 0.2
+         z: 1
+     }
+     ImageParticle {
+         system: sys
+         groups: ["frigateShield"]
+         source: "pics/blur-circle2.png"
+         color: "#00000000"
+         colorVariation: 0.05
+         blueVariation: 0.5
+         greenVariation: 0.1
+         z: 3
+     }
+     ImageParticle {
+         system: sys
+         groups: ["cruiserArmor"]
+         z: 1
+         sprites:[Sprite {
+                 id: spinState
+                 name: "spinning"
+                 source: "pics/meteor.png"
+                 frameCount: 35
+                 frameDuration: 40
+                 to: {"death":0, "spinning":1}
+             },Sprite {
+                 name: "death"
+                 source: "pics/meteor_explo.png"
+                 frameCount: 22
+                 frameDuration: 40
+                 to: {"null":1}
+             }, Sprite {
+                 name: "null"
+                 source: "pics/nullRock.png"
+                 frameCount: 1
+                 frameDuration: 1000
+             }
+         ]
+     }
+     TrailEmitter {
+         system: sys
+         group: "cannonWake"
+         follow: "cannon"
+         emitRatePerParticle: 64
+         lifeSpan: 600
+         speed: AngleDirection { angleVariation: 360; magnitude: 48}
+         size: 16
+         endSize: 8
+         sizeVariation: 2
+         enabled: true
+         width: 1000//XXX: Terrible hack
+         height: 1000
+     }
+     TrailEmitter {
+         system: sys
+         group: "cannonCore"
+         follow: "cannon"
+         emitRatePerParticle: 256
+         lifeSpan: 128
+         size: 24
+         endSize: 8
+         enabled: true
+         width: 1000//XXX: Terrible hack
+         height: 1000
+     }
+ }
index 0000000,eaef87f..3707759
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,54 +1,54 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: container
+     //TODO: Somehow get particles into this?
+     property list<Component> pages
+     property Item cur: null
+     property int at: 0
+     function advance() {
+         if(cur != null)
+             cur.destroy();
+         cur = pages[at++].createObject(container);
+     }
+ }
index 0000000,a928cd2..bd023b1
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,114 +1,114 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     id: me
+     //Reflective Properties
+     width: shipLoader.width
+     height: shipLoader.height
+     //Transfered Properties
+     property int hp: 100//shipLoader.item.maxHP
+     property real dodge: shipLoader.item.initialDodge
+     property ParticleSystem system
+     property int targetIdx: 0
+     property Item target: targets[targetIdx] == undefined?null:targets[targetIdx]
+     Connections {
+         target: me.target
+         onHpChanged: if (me.target.hp<=0) me.targetIdx++;
+     }
+     property list<Item> targets
+     property string shipParticle: "default"//Per team colors?
+     property int gunType: 0
+     property int shipType: 0
+     Component {
+         id: sloopComp
+         Sloop {
+             system: me.system
+             target: me.target
+             shipParticle: me.shipParticle
+             gunType: me.gunType
+             hp: me.hp
+             dodge: me.dodge
+         }
+     }
+     Component {
+         id: frigateComp
+         Frigate {
+             system: me.system
+             target: me.target
+             shipParticle: me.shipParticle
+             gunType: me.gunType
+             hp: me.hp
+             dodge: me.dodge
+         }
+     }
+     Component {
+         id: cruiserComp
+         Cruiser {
+             system: me.system
+             target: me.target
+             shipParticle: me.shipParticle
+             gunType: me.gunType
+             hp: me.hp
+             dodge: me.dodge
+         }
+     }
+     Component {
+         id: dumbComp
+         Item {
+             property int maxHP: 0
+             property int initialDodge: 0
+         }
+     }
+     Loader {
+         id: shipLoader
+         sourceComponent: {
+             switch (shipType) {
+             case 1: sloopComp; break;
+             case 2: frigateComp; break;
+             case 3: cruiserComp; break;
+             default: dumbComp;
+             }
+         }
+     }
+ }
index 0000000,c6b1183..3bc58a2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,108 +1,108 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     id: container
+     property int maxHP: 100
+     property int hp: maxHP
+     property real initialDodge: 0.5
+     property real dodge: initialDodge
+     property int blinkInterval: 800
+     onHpChanged: if(hp <= 0) target = container;
+     property ParticleSystem system//TODO: Ship abstraction
+     property Item target: container
+     property string shipParticle: "default"//Per team colors?
+     property int gunType: 0
+     width: 128
+     height: 128
+     Emitter {
+         id: emitter
+         //TODO: Cooler would be an 'orbiting' affector
+         //TODO: On the subject, opacity and size should be grouped type 'overLife' if we can cram that in the particles
+         system: container.system
+         group: container.shipParticle
+         shape: EllipseShape {}
+         emitRate: hp > 0 ?  hp + 20 : 0 
+         lifeSpan: blinkInterval
+         maximumEmitted: (maxHP + 20)
+         acceleration: AngleDirection {angleVariation: 360; magnitude: 8}
+         size: 24
+         endSize: 4
+         sizeVariation: 8
+         width: 16
+         height: 16
+         x: 64
+         y: 64
+         Behavior on x {NumberAnimation {duration:blinkInterval}}
+         Behavior on y {NumberAnimation {duration:blinkInterval}}
+         Timer {
+             interval: blinkInterval
+             running: true
+             repeat: true
+             onTriggered: {
+                 emitter.x = Math.random() * 48 + 32
+                 emitter.y = Math.random() * 48 + 32
+             }
+         }
+     }
+     Hardpoint {
+         anchors.centerIn: parent
+         id: gun2
+         system: container.system
+         show: container.hp > 0
+         hardpointType: gunType
+     }
+     Timer {
+         id: fireControl
+         interval: 800
+         running: root.readySetGo
+         repeat: true
+         onTriggered: {
+                 gun2.fireAt(container.target);
+         }
+     }
+ }
index 0000000,45f81c7..b14ac63
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,386 +1,386 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ import "content"
+ Rectangle {
+     id: root
+     property bool readySetGo: false
+     //Debugging
+     property int hits: 0
+     property int misses: 0
+     property real ratio: hits/(misses?misses:1)
+     //Move to JS file?
+     property Ship redVar1: Ship {shipType: 1; gunType: 1}
+     property Ship redVar2: Ship {shipType: 1; gunType: 2}
+     property Ship redVar3: Ship {shipType: 1; gunType: 3}
+     property Ship greenVar1: Ship {shipType: 3; gunType: 1}
+     property Ship greenVar2: Ship {shipType: 2; gunType: 2}
+     property Ship greenVar3: Ship {shipType: 1; gunType: 3}
+     property string winner: "0"
+     property int players: 0
+     function aiSet(ship) {
+         ship.gunType = Math.floor(Math.random() * 3) + 1
+         ship.shipType = Math.floor(Math.random() * 3) + 1
+     }
+     width: 360
+     height: 600
+     color: "black"
+     SequentialLoader {
+         anchors.fill: parent
+         //General Children
+         Image {
+             anchors.centerIn: parent
+             source: "../images/finalfrontier.png"
+         }
+         ParticleSystem {
+             id: particles
+         }
+         PlasmaPatrolParticles { sys: particles; z: 100 }//Renders all particles on the one plane
+         //Component parts
+         id: pageControl
+         Component.onCompleted: advance();
+         pages:[
+         Component {Item {
+             id: menu
+             width: root.width
+             height: root.height
+             Column {
+                 anchors.verticalCenter: parent.verticalCenter
+                 width: parent.width
+                 spacing: 8
+                 Item {
+                     id: title
+                     width: root.width
+                     height: 240
+                     Emitter {
+                         anchors.fill: parent
+                         system: particles
+                         enabled: true
+                         group: "default"
+                         emitRate: 1200
+                         lifeSpan: 1200
+                         shape: MaskShape {source:"content/pics/TitleText.png"}
+                         size: 16
+                         endSize: 0
+                         sizeVariation: 8
+                         speed: AngleDirection {angleVariation:360; magnitudeVariation: 6}
+                     }
+                 }
+                 Button {
+                     text: "1P"
+                     onClicked: {root.players = 1; pageControl.advance();}
+                     anchors.horizontalCenter: parent.horizontalCenter
+                 }
+                 Button {
+                     text: "2P"
+                     onClicked: {root.players = 2; pageControl.advance();}
+                     anchors.horizontalCenter: parent.horizontalCenter
+                 }
+                 Button {
+                     text: "Demo"
+                     anchors.horizontalCenter: parent.horizontalCenter
+                     onClicked: {root.players = 0; 
+                         aiSet(redVar1);
+                         aiSet(redVar2);
+                         aiSet(redVar3);
+                         aiSet(greenVar1);
+                         aiSet(greenVar2);
+                         aiSet(greenVar3);
+                         pageControl.at = 5;//TODO: Not a magic number
+                         pageControl.advance();}
+                 }
+                 Button {
+                     text: "Help"
+                     anchors.horizontalCenter: parent.horizontalCenter
+                     onClicked: {
+                         pageControl.at = 7;//TODO: Not a magic number
+                         pageControl.advance();
+                     }
+                 }
+                 Button {
+                     text: "Quit"
+                     anchors.horizontalCenter: parent.horizontalCenter
+                     onClicked: Qt.quit();
+                 }
+             }
+         }},
+         Component {Item {
+             id: p1Screen
+             z: 101
+             width: root.width
+             height: root.height
+             Rectangle {
+                 anchors.fill: parent
+                 color: "red"
+             }
+             Text {
+                 anchors.centerIn: parent
+                 color: "white"
+                 font.pixelSize: 64
+                 font.bold: true
+                 text: "Player\n    1"
+                 horizontalAlignment: Text.AlignHCenter
+             }
+             MouseArea {
+                 anchors.fill: parent
+                 onClicked: pageControl.advance()
+             }
+         }},
+         Component {Item {
+             id: p1Choices
+             z: 3
+             width: root.width
+             height: root.height
+             Rectangle {
+                 color: "black"
+                 anchors.fill: parent
+             }
+             Column {
+                 spacing: 16
+                 width: root.width
+                 anchors.horizontalCenter: parent.horizontalCenter
+                 ChoiceBox {
+                     target: redVar1
+                     system: particles
+                 }
+                 ChoiceBox {
+                     target: redVar2
+                     system: particles
+                 }
+                 ChoiceBox {
+                     target: redVar3
+                     system: particles
+                 }
+                 Button {
+                     anchors.horizontalCenter: parent.horizontalCenter
+                     text: "Next"
+                     onClicked: {
+                         if (root.players < 2) {
+                             aiSet(greenVar1);
+                             aiSet(greenVar2);
+                             aiSet(greenVar3);
+                             pageControl.at = 5;//TODO: Not a magic number
+                         }
+                         pageControl.advance();
+                     }
+                 }
+             }
+         }},
+         Component {Item {
+             id: p2Screen
+             z: 101
+             width: root.width
+             height: root.height
+             Rectangle {
+                 anchors.fill: parent
+                 color: "green"
+             }
+             Text {
+                 anchors.centerIn: parent
+                 color: "white"
+                 font.pixelSize: 64
+                 font.bold: true
+                 text: "Player\n    2"
+                 horizontalAlignment: Text.AlignHCenter
+             }
+             MouseArea {
+                 anchors.fill: parent
+                 onClicked: pageControl.advance()
+             }
+         }},
+         Component {Item {
+             id: p2Choices
+             z: 1
+             width: root.width
+             height: root.height
+             Rectangle {
+                 color: "black"
+                 anchors.fill: parent
+             }
+             Column {
+                 spacing: 16
+                 width: root.width
+                 anchors.horizontalCenter: parent.horizontalCenter
+                 ChoiceBox {
+                     target: greenVar1
+                     system: particles
+                 }
+                 ChoiceBox {
+                     target: greenVar2
+                     system: particles
+                 }
+                 ChoiceBox {
+                     target: greenVar3
+                     system: particles
+                 }
+                 Button {
+                     anchors.horizontalCenter: parent.horizontalCenter
+                     text: "Next"
+                     onClicked: pageControl.advance()
+                 }
+             }
+         }},
+         Component {Item {
+             id: arena
+             width: root.width
+             height: root.height
+             z: 0
+             Component.onCompleted: root.readySetGo = true
+             Component.onDestruction: root.readySetGo = false
+             property bool victory: redShip3.hp <= 0 || greenShip3.hp <=0
+             onVictoryChanged: {
+                 if (redShip3.hp <= 0) {
+                     if (greenShip3.hp <= 0) {
+                         root.winner = "1&2"
+                     }else {
+                         root.winner = "2"
+                     }
+                 } else {
+                     root.winner = "1"
+                 }
+                 winTimer.start()
+             }
+             Timer {
+                 id: winTimer
+                 interval: 1200
+                 repeat: false
+                 running: false
+                 onTriggered: pageControl.advance();
+             }
+             Ship {
+                 id: redShip1
+                 shipParticle: "redTeam"
+                 system: particles
+                 x: 180-64
+                 y: 128
+                 shipType: redVar1.shipType
+                 gunType: redVar1.gunType
+                 targets: [greenShip1, greenShip2, greenShip3]
+             }
+             Ship {
+                 id: redShip2
+                 shipParticle: "redTeam"
+                 system: particles
+                 x: 0
+                 y: 0
+                 shipType: redVar2.shipType
+                 gunType: redVar2.gunType
+                 targets: [greenShip1, greenShip2, greenShip3]
+             }
+             Ship {
+                 id: redShip3
+                 shipParticle: "redTeam"
+                 system: particles
+                 x: 360-128
+                 y: 0
+                 shipType: redVar3.shipType
+                 gunType: redVar3.gunType
+                 targets: [greenShip1, greenShip2, greenShip3]
+             }
+             Ship {
+                 id: greenShip1
+                 shipParticle: "greenTeam"
+                 system: particles
+                 x: 180-64
+                 y: 600 - 128 - 128
+                 shipType: greenVar1.shipType
+                 gunType: greenVar1.gunType
+                 targets: [redShip1, redShip2, redShip3]
+             }
+             Ship {
+                 id: greenShip2
+                 shipParticle: "greenTeam"
+                 system: particles
+                 x: 0
+                 y: 600-128
+                 shipType: greenVar2.shipType
+                 gunType: greenVar2.gunType
+                 targets: [redShip1, redShip2, redShip3]
+             }
+             Ship {
+                 id: greenShip3
+                 shipParticle: "greenTeam"
+                 system: particles
+                 x: 360 - 128
+                 y: 600 - 128
+                 shipType: greenVar3.shipType
+                 gunType: greenVar3.gunType
+                 targets: [redShip1, redShip2, redShip3]
+             }
+         }},
+         Component {Item {
+             id: winScreen
+             z: 101
+             width: root.width
+             height: root.height
+             /*
+             Rectangle {
+                 anchors.fill: parent
+                 color: "black"
+             }
+             */
+             Text {//TODO: Particle Text?
+                 anchors.fill: parent
+                 color: "white"
+                 font.pixelSize: 64
+                 font.bold: true
+                 text: "Player " + root.winner + " wins!"
+                 wrapMode: Text.WordWrap
+                 horizontalAlignment: Text.AlignHCenter
+                 verticalAlignment: Text.AlignVCenter
+             }
+             MouseArea {
+                 anchors.fill: parent
+                 onClicked: {pageControl.at = 0; pageControl.advance();}
+             }
+         }},
+         Component {
+             HelpScreens {
+                 onExitDesired: {pageControl.at = 0; pageControl.advance();}
+             }
+         }
+         ]
+     }
+ }
index 0000000,b6264ea..f1abd11
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,53 +1,53 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Image {
+     id: container
+     property bool on: false
+     source: "images/busy.png"; visible: container.on
+     NumberAnimation on rotation {
+         running: container.on; from: 0; to: 360; loops: Animation.Infinite; duration: 1200
+     }
+ }
index 0000000,1a56184..fe64238
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,82 +1,82 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: delegate
+     width: delegate.ListView.view.width; height: 60
+     Text {
+         text: name
+         color: delegate.ListView.isCurrentItem ? "white" : "black"
+         font { family: "Helvetica"; pixelSize: 16; bold: true }
+         anchors {
+             left: parent.left; leftMargin: 15
+             verticalCenter: parent.verticalCenter
+         }
+     }
+     BusyIndicator {
+         scale: 0.6
+         on: delegate.ListView.isCurrentItem && window.loading
+         anchors { right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter }
+     }
+     Rectangle {
+         width: delegate.width; height: 1; color: "#cccccc"
+         anchors.bottom: delegate.bottom
+         visible: delegate.ListView.isCurrentItem ? false : true
+     }
+     Rectangle {
+         width: delegate.width; height: 1; color: "white"
+         visible: delegate.ListView.isCurrentItem ? false : true
+     }
+     MouseArea {
+         anchors.fill: delegate
+         onClicked: {
+             delegate.ListView.view.currentIndex = index
+             window.currentFeed = feed
+         }
+     }
+ }
index 0000000,84019a9..59ab269
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,71 +1,71 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: delegate
+     height: column.height + 40
+     width: delegate.ListView.view.width
+     Column {
+         id: column
+         x: 20; y: 20
+         width: parent.width - 40
+         Text {
+             id: titleText
+             text: title; width: parent.width; wrapMode: Text.WordWrap
+             font { bold: true; family: "Helvetica"; pointSize: 16 }
+         }
+         Text {
+             id: descriptionText
+             width: parent.width; text: description
+             wrapMode: Text.WordWrap; font.family: "Helvetica"
+         }
+     }
+     Rectangle {
+         width: parent.width; height: 1; color: "#cccccc"
+         anchors.bottom: parent.bottom
+     }
+ }
index 0000000,278f057..ed58ef3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,59 +1,59 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ ListModel {
+     id: rssFeeds
+     ListElement { name: "Top Stories"; feed: "rss.news.yahoo.com/rss/topstories" }
+     ListElement { name: "World"; feed: "rss.news.yahoo.com/rss/world" }
+     ListElement { name: "Europe"; feed: "rss.news.yahoo.com/rss/europe" }
+     ListElement { name: "Oceania"; feed: "rss.news.yahoo.com/rss/oceania" }
+     ListElement { name: "U.S. National"; feed: "rss.news.yahoo.com/rss/us" }
+     ListElement { name: "Politics"; feed: "rss.news.yahoo.com/rss/politics" }
+     ListElement { name: "Business"; feed: "rss.news.yahoo.com/rss/business" }
+     ListElement { name: "Technology"; feed: "rss.news.yahoo.com/rss/tech" }
+     ListElement { name: "Entertainment"; feed: "rss.news.yahoo.com/rss/entertainment" }
+     ListElement { name: "Health"; feed: "rss.news.yahoo.com/rss/health" }
+     ListElement { name: "Science"; feed: "rss.news.yahoo.com/rss/science" }
+     ListElement { name: "Sports"; feed: "rss.news.yahoo.com/rss/sports" }
+ }
index 0000000,4ca4132..7b1a2ac
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,107 +1,107 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: container
+     property variant scrollArea
+     property variant orientation: Qt.Vertical
+     opacity: 0
+     function position()
+     {
+         var ny = 0;
+         if (container.orientation == Qt.Vertical)
+             ny = scrollArea.visibleArea.yPosition * container.height;
+         else
+             ny = scrollArea.visibleArea.xPosition * container.width;
+         if (ny > 2) return ny; else return 2;
+     }
+     function size()
+     {
+         var nh, ny;
+         if (container.orientation == Qt.Vertical)
+             nh = scrollArea.visibleArea.heightRatio * container.height;
+         else
+             nh = scrollArea.visibleArea.widthRatio * container.width;
+         if (container.orientation == Qt.Vertical)
+             ny = scrollArea.visibleArea.yPosition * container.height;
+         else
+             ny = scrollArea.visibleArea.xPosition * container.width;
+         if (ny > 3) {
+             var t;
+             if (container.orientation == Qt.Vertical)
+                 t = Math.ceil(container.height - 3 - ny);
+             else
+                 t = Math.ceil(container.width - 3 - ny);
+             if (nh > t) return t; else return nh;
+         } else return nh + ny;
+     }
+     Rectangle { anchors.fill: parent; color: "Black"; opacity: 0.3 }
+     BorderImage {
+         source: "images/scrollbar.png"
+         border { left: 1; right: 1; top: 1; bottom: 1 }
+         x: container.orientation == Qt.Vertical ? 2 : position()
+         width: container.orientation == Qt.Vertical ? container.width - 4 : size()
+         y: container.orientation == Qt.Vertical ? position() : 2
+         height: container.orientation == Qt.Vertical ? size() : container.height - 4
+     }
+     states: State {
+         name: "visible"
+         when: container.orientation == Qt.Vertical ? scrollArea.movingVertically : scrollArea.movingHorizontally
+         PropertyChanges { target: container; opacity: 1.0 }
+     }
+     transitions: Transition {
+         from: "visible"; to: ""
+         NumberAnimation { properties: "opacity"; duration: 600 }
+     }
+ }
index 0000000,491cefd..d26b94b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,112 +1,112 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.XmlListModel 2.0
+ import "content"
+ Rectangle {
+     id: window
+     width: 800; height: 480
+     property string currentFeed: "rss.news.yahoo.com/rss/topstories"
+     property bool loading: feedModel.status == XmlListModel.Loading
+     RssFeeds { id: rssFeeds }
+     XmlListModel {
+         id: feedModel
+         source: "http://" + window.currentFeed
+         query: "/rss/channel/item"
+         XmlRole { name: "title"; query: "title/string()" }
+         XmlRole { name: "link"; query: "link/string()" }
+         XmlRole { name: "description"; query: "description/string()" }
+     }
+     Row {
+         Rectangle {
+             width: 220; height: window.height
+             color: "#efefef"
+             ListView {
+                 focus: true
+                 id: categories
+                 anchors.fill: parent
+                 model: rssFeeds
+                 footer: quitButtonDelegate
+                 delegate: CategoryDelegate {}
+                 highlight: Rectangle { color: "steelblue" }
+                 highlightMoveSpeed: 9999999
+             }
+             ScrollBar {
+                 scrollArea: categories; height: categories.height; width: 8
+                 anchors.right: categories.right
+             }
+         }
+         ListView {
+             id: list
+             width: window.width - 220; height: window.height
+             model: feedModel
+             delegate: NewsDelegate {}
+         }
+     }
+     Component {
+         id: quitButtonDelegate
+         Item {
+             width: categories.width; height: 60
+             Text {
+                 text: "Quit"
+                 font { family: "Helvetica"; pixelSize: 16; bold: true }
+                 anchors {
+                     left: parent.left; leftMargin: 15
+                     verticalCenter: parent.verticalCenter
+                 }
+             }
+             MouseArea {
+                 anchors.fill: parent
+                 onClicked: Qt.quit()
+             }
+         }
+     }
+     ScrollBar { scrollArea: list; height: list.height; width: 8; anchors.right: window.right }
+     Rectangle { x: 220; height: window.height; width: 1; color: "#cccccc" }
+ }
index 0000000,47f86bd..a348368
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,112 +1,112 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item {
+     id: block
+     property bool dying: false
+     property bool spawned: false
+     property int type: 0
+     property ParticleSystem particleSystem
+     Behavior on x {
+         enabled: spawned;
+         SpringAnimation{ spring: 2; damping: 0.2 }
+     }
+     Behavior on y {
+         SpringAnimation{ spring: 2; damping: 0.2 }
+     }
+     Image {
+         id: img
+         source: {
+             if(type == 0){
+                 "pics/redStone.png";
+             } else if(type == 1) {
+                 "pics/blueStone.png";
+             } else {
+                 "pics/greenStone.png";
+             }
+         }
+         opacity: 0
+         Behavior on opacity { NumberAnimation { duration: 200 } }
+         anchors.fill: parent
+     }
+     Emitter {
+         id: particles
+         system: particleSystem
+         group: { 
+             if(type == 0){
+                 "red";
+             } else if (type == 1) {
+                 "blue";
+             } else {
+                 "green";
+             }
+         }
+         anchors.fill: parent
+         speed: TargetDirection{targetX: block.width/2; targetY: block.height/2; magnitude: -60; magnitudeVariation: 60}
+         shape: EllipseShape{fill:true}
+         enabled: false;
+         lifeSpan: 700; lifeSpanVariation: 100
+         emitRate: 1000
+         maximumEmitted: 100 //only fires 0.1s bursts (still 2x old number)
+         size: 28
+         endSize: 14
+     }
+     states: [
+         State {
+             name: "AliveState"; when: spawned == true && dying == false
+             PropertyChanges { target: img; opacity: 1 }
+         },
+         State {
+             name: "DeathState"; when: dying == true
+             StateChangeScript { script: {particleSystem.paused = false; particles.pulse(100);} }
+             PropertyChanges { target: img; opacity: 0 }
+             StateChangeScript { script: block.destroy(1000); }
+         }
+     ]
+ }
index 0000000,b305455..2d1a993
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,75 +1,75 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Rectangle {
+     id: container
+     property string text: "Button"
+     signal clicked
+     width: buttonLabel.width + 20; height: buttonLabel.height + 20
+     smooth: true
+     border { width: 1; color: Qt.darker(activePalette.button) }
+     radius: 8
+     color: activePalette.button
+     gradient: Gradient {
+         GradientStop {
+             position: 0.0
+             color: {
+                 if (mouseArea.pressed)
+                     return activePalette.dark
+                 else
+                     return activePalette.light
+             }
+         }
+         GradientStop { position: 1.0; color: activePalette.button }
+     }
+     MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked() }
+     Text {
+         id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText; font.pixelSize: 24
+     }
+ }
index 0000000,80e5984..c81580e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,81 +1,81 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Rectangle {
+     id: page
+     anchors.centerIn: parent
+     property Item text: dialogText
+     property bool open: false
+     signal closed
+     signal opened
+     function forceClose() {
+         if(!open)
+             return; //already closed
+         page.open = false;
+         page.closed();
+         page.opacity = 0;
+     }
+     function show(txt) {
+         page.open = true;
+         page.opened();
+         dialogText.text = txt;
+         page.opacity = 1;
+     }
+     width: dialogText.width + 20; height: dialogText.height + 20
+     color: "white"
+     border.width: 1
+     opacity: 0
+     visible: opacity > 0
+     Behavior on opacity {
+         NumberAnimation { duration: 1000 }
+     }
+     Text { id: dialogText; anchors.centerIn: parent; text: "Hello World!" }
+     MouseArea { anchors.fill: parent; onClicked: forceClose(); }
+ }
index 0000000,a43d551..3422582
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,92 +1,92 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ import "samegame.js" as Logic
+ Item {
+     id: gameCanvas
+     property int score: 0
+     property int blockSize: 40
+     property ParticleSystem ps: particleSystem
+     Image {
+         id: background
+         anchors.fill: parent
+         z: -1
+         source: "pics/background.png"
+         fillMode: Image.PreserveAspectCrop
+     }
+     width: 480
+     height: 800
+     MouseArea {
+         anchors.fill: parent; onClicked: Logic.handleClick(mouse.x,mouse.y);
+     }
+     ParticleSystem{ 
+         id: particleSystem;
+         onEmptyChanged: if (empty) paused = true;
+         z:2
+         ImageParticle {
+             groups: ["red"]
+             color: Qt.darker("red");//Actually want desaturated...
+             source: "pics/particle.png"
+             colorVariation: 0.4
+             alpha: 0.1
+         }
+         ImageParticle {
+             groups: ["green"]
+             color: Qt.darker("green");//Actually want desaturated...
+             source: "pics/particle.png"
+             colorVariation: 0.4
+             alpha: 0.1
+         }
+         ImageParticle {
+             groups: ["blue"]
+             color: Qt.darker("blue");//Actually want desaturated...
+             source: "pics/particle.png"
+             colorVariation: 0.4
+             alpha: 0.1
+         }
+         anchors.fill: parent
+     }
+ }
index 0000000,602e697..7c3bfa2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,93 +1,93 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Dialog {
+     id: nameInputDialog
+     property int initialWidth: 0
+     property alias name: nameInputText.text
+     anchors.centerIn: parent
+     z: 22;
+     Behavior on width {
+         NumberAnimation {} 
+         enabled: nameInputDialog.initialWidth != 0
+     }
+     signal accepted(string name)
+     onClosed: {
+         if (nameInputText.text != "")
+             accepted(name);
+     }
+     Text {
+         id: dialogText
+         anchors { left: nameInputDialog.left; leftMargin: 20; verticalCenter: parent.verticalCenter }
+         text: "You won! Please enter your name: "
+     }
+     MouseArea {
+         anchors.fill: parent
+         onClicked: {
+             if (nameInputText.text == "")
+                 nameInputText.openSoftwareInputPanel();
+             else
+                 nameInputDialog.forceClose();
+         }
+     }
+     TextInput {
+         id: nameInputText
+         anchors { verticalCenter: parent.verticalCenter; left: dialogText.right }
+         focus: visible
+         autoScroll: false
+         maximumLength: 24
+         onTextChanged: {
+             var newWidth = nameInputText.width + dialogText.width + 40;
+             if ( (newWidth > nameInputDialog.width && newWidth < screen.width) 
+                     || (nameInputDialog.width > nameInputDialog.initialWidth) )
+                 nameInputDialog.width = newWidth;
+         }
+         onAccepted: {
+             nameInputDialog.forceClose();
+         }
+     }
+ }
index 0000000,201f826..b98b6a0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,87 +1,87 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ import "content"
+ import "content/samegame.js" as Logic
+ Rectangle {
+     id: screen
+     width: 480; height: 640
+     SystemPalette { id: activePalette }
+     GameArea {
+         id: gameCanvas
+         width: parent.width
+         anchors { top: parent.top; bottom: toolBar.top }
+     }
+     Rectangle {
+         id: toolBar
+         width: parent.width; height: 80
+         color: activePalette.window
+         anchors.bottom: screen.bottom
+         Button {
+             id: newGameButton
+             anchors { left: parent.left; leftMargin: 12; verticalCenter: parent.verticalCenter }
+             text: "New Game" 
+             onClicked: Logic.startNewGame(gameCanvas)
+         }
+         Button {
+             text: "Quit"
+             anchors { left: newGameButton.right; leftMargin: 12; verticalCenter: parent.verticalCenter }
+             onClicked: Qt.quit();
+         }
+         Text {
+             id: score
+             anchors { right: parent.right; rightMargin: 12; verticalCenter: parent.verticalCenter }
+             text: "Score: " + gameCanvas.score
+             font.bold: true
+             font.pixelSize: 24
+             color: activePalette.windowText
+         }
+     }
+ }
index 0000000,dfac450..4f29455
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,66 +1,66 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Rectangle {
+     id: container
+     signal clicked
+     property string text: "Button"
+     color: activePalette.button; smooth: true
+     width: txtItem.width + 20; height: txtItem.height + 6
+     border.width: 1; border.color: Qt.darker(activePalette.button); radius: 8;
+     gradient: Gradient {
+         GradientStop {
+             id: topGrad; position: 0.0
+             color: if (mr.pressed) { activePalette.dark } else { activePalette.light } }
+         GradientStop { position: 1.0; color: activePalette.button }
+     }
+     MouseArea { id: mr; anchors.fill: parent; onClicked: container.clicked() }
+     Text {
+         id: txtItem; text: container.text; anchors.centerIn: container; color: activePalette.buttonText
+     }
+ }
index 0000000,cae53af..35ffe40
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,102 +1,102 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item  {
+     id: root
+     property bool dying: false
+     property int row;
+     property int column;
+     x: margin + column * gridSize
+     y: margin + row * gridSize
+     width: gridSize
+     height: gridSize
+     property int value : 1;
+     Image {
+         id: img
+         anchors.fill: parent
+         source: "pics/cookie.png"
+         opacity: 0
+         Text {
+             font.bold: true
+             anchors.verticalCenter: parent.verticalCenter
+             anchors.horizontalCenter: parent.horizontalCenter
+             text: value
+         }
+     }
+     ParticleSystem {
+         width:1; height:1; anchors.centerIn: parent;
+         ImageParticle {
+             groups: ["star"]
+             source: "pics/yellowStar.png"
+         }
+         Emitter {
+             id: particles
+             anchors.fill: parent
+             group: "star"
+             emitRate: 50
+             enabled: false
+             lifeSpan: 700
+             acceleration: AngleDirection { angleVariation: 360; magnitude: 200 }
+         }
+     }
+     states: [
+         State{ name: "AliveState"; when: dying == false
+             PropertyChanges { target: img; opacity: 1 }
+         },
+         State{ name: "DeathState"; when: dying == true
+             StateChangeScript { script: particles.burst(50); }
+             PropertyChanges { target: img; opacity: 0 }
+         }
+     ]
+     transitions: [
+         Transition {
+             NumberAnimation { target: img; property: "opacity"; duration: 100 }
+         }
+     ]
+ }
index 0000000,af66b99..734a661
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,140 +1,140 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.LocalStorage 2.0 as Sql
+ // Models a high score table.
+ //
+ // Use this component like this:
+ //
+ //  HighScoreModel {
+ //      id: highScores
+ //      game: "MyCoolGame"
+ //  }
+ //
+ // Then use either use the top-score properties:
+ //
+ //  Text { text: "HI: " + highScores.topScore }
+ //
+ // or, use the model in a view:
+ //
+ //  ListView {
+ //      model: highScore
+ //      delegate: Component {
+ //                    ... player ... score ...
+ //                }
+ //  }
+ //
+ // Add new scores via:
+ //
+ //  saveScore(newScore)
+ //
+ // or:
+ //
+ //  savePlayerScore(playerName,newScore)
+ //
+ // The best maxScore scores added by this method will be retained in an SQL database,
+ // and presented in the model and in the topScore/topPlayer properties.
+ //
+ ListModel {
+     id: model
+     property string game: ""
+     property int topScore: 0
+     property string topPlayer: ""
+     property int maxScores: 10
+     function __db()
+     {
+         return Sql.openDatabaseSync("HighScoreModel", "1.0", "Generic High Score Functionality for QML", 1000000);
+     }
+     function __ensureTables(tx)
+     {
+         tx.executeSql('CREATE TABLE IF NOT EXISTS HighScores(game TEXT, score INT, player TEXT)', []);
+     }
+     function fillModel() {
+         __db().transaction(
+             function(tx) {
+                 __ensureTables(tx);
+                 var rs = tx.executeSql("SELECT score,player FROM HighScores WHERE game=? ORDER BY score DESC", [game]);
+                 model.clear();
+                 if (rs.rows.length > 0) {
+                     topScore = rs.rows.item(0).score
+                     topPlayer = rs.rows.item(0).player
+                     for (var i=0; i<rs.rows.length; ++i) {
+                         if (i < maxScores)
+                             model.append(rs.rows.item(i))
+                     }
+                     if (rs.rows.length > maxScores)
+                         tx.executeSql("DELETE FROM HighScores WHERE game=? AND score <= ?",
+                                             [game, rs.rows.item(maxScores).score]);
+                 }
+             }
+         )
+     }
+     function savePlayerScore(player,score) {
+         __db().transaction(
+             function(tx) {
+                 __ensureTables(tx);
+                 tx.executeSql("INSERT INTO HighScores VALUES(?,?,?)", [game,score,player]);
+                 fillModel();
+             }
+         )
+     }
+     function saveScore(score) {
+         savePlayerScore("player",score);
+     }
+     function clearScores() {
+         __db().transaction(
+             function(tx) {
+                 tx.executeSql("DELETE FROM HighScores WHERE game=?", [game]);
+                 fillModel();
+             }
+         )
+     }
+     Component.onCompleted: { fillModel() }
+ }
index 0000000,891adaf..aab005a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,129 +1,129 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.Particles 2.0
+ Item { id:link
+     property bool dying: false
+     property bool spawned: false
+     property int type: 0
+     property int row: 0
+     property int column: 0
+     property int rotation;
+     width: 40;
+     height: 40
+     x: margin - 3 + gridSize * column
+     y: margin - 3 + gridSize * row
+     Behavior on x { NumberAnimation { duration: spawned ? heartbeatInterval : 0} }
+     Behavior on y { NumberAnimation { duration: spawned ? heartbeatInterval : 0 } }
+     Item {
+         id: img
+         anchors.fill: parent
+         Image {
+             source: {
+                 if(type == 1) {
+                     "pics/blueStone.png";
+                 } else if (type == 2) {
+                     "pics/head.png";
+                 } else {
+                     "pics/redStone.png";
+                 }
+             }
+             transform: Rotation {
+                 id: actualImageRotation
+                 origin.x: width/2; origin.y: height/2;
+                 angle: rotation * 90
+                 Behavior on angle {
+                     RotationAnimation{
+                         direction: RotationAnimation.Shortest
+                         duration: spawned ? 200 : 0
+                     }
+                 }
+             }
+         }
+         Image {
+             source: "pics/stoneShadow.png"
+         }
+         opacity: 0
+     }
+     ParticleSystem {
+         width:1; height:1; anchors.centerIn: parent;
+         ImageParticle {
+             groups: ["star"]
+             source: type == 1 ? "pics/blueStar.png" : "pics/redStar.png"
+         }
+         Emitter {
+             id: particles
+             anchors.fill: parent
+             group: "star"
+             emitRate: 50
+             enabled: false
+             lifeSpan: 700
+             acceleration: AngleDirection { angleVariation: 360; magnitude: 200 }
+         }
+     }
+     states: [
+         State{ name: "AliveState"; when: spawned == true && dying == false
+             PropertyChanges { target: img; opacity: 1 }
+         },
+         State{ name: "DeathState"; when: dying == true
+             StateChangeScript { script: particles.burst(50); }
+             PropertyChanges { target: img; opacity: 0 }
+         }
+     ]
+     transitions: [
+         Transition {
+             NumberAnimation { target: img; property: "opacity"; duration: 200 }
+         }
+     ]
+ }
index 0000000,9026790..0c173be
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,62 +1,62 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Image {
+     property bool spawned: false
+     property int row;
+     property int column;
+     property int verticalMovement;
+     property int horizontalMovement;
+     x: screen.margin + column * screen.gridSize + 2
+     y: screen.margin + row * screen.gridSize - 3
+     Behavior on x { NumberAnimation { duration: spawned ? screen.halfbeatInterval : 0} }
+     Behavior on y { NumberAnimation { duration: spawned ? screen.halfbeatInterval : 0 } }
+     opacity: spawned ? 1 : 0
+     Behavior on opacity { NumberAnimation { duration: 200 } }
+     source: "pics/skull.png"
+     width: 24
+     height: 40
+ }
index 0000000,fca3273..efd5747
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,273 +1,273 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import "content" as Content
+ import "content/snake.js" as Logic
+ Item{
+ Rectangle {
+     id: screen;
+     SystemPalette { id: activePalette }
+     color: activePalette.window
+     property bool activeGame: false
+     property int gridSize : 34
+     property int margin: 4
+     property int numRowsAvailable: Math.floor((height-32-2*margin)/gridSize)
+     property int numColumnsAvailable: Math.floor((width-2*margin)/gridSize)
+     property int lastScore : 0
+     property int score: 0;
+     property int heartbeatInterval: 200
+     property int halfbeatInterval: 160
+     width: 480
+     height: 750
+     property int direction
+     property int headDirection
+     property variant head;
+     Content.HighScoreModel {
+         id: highScores
+         game: "Snake"
+     }
+     Timer {
+         id: heartbeat;
+         interval: screen.heartbeatInterval;
+         running: screen.activeGame
+         repeat: true
+         onTriggered: { Logic.move() }
+     }
+     Timer {
+         id: halfbeat;
+         interval: screen.halfbeatInterval;
+         repeat: true
+         running: heartbeat.running
+         onTriggered: { Logic.moveSkull() }
+     }
+     Timer {
+         id: startNewGameTimer;
+         interval: 700;
+         onTriggered: { Logic.startNewGame(); }
+     }
+     Timer {
+         id: startHeartbeatTimer;
+         interval: 1000 ;
+         onTriggered: { screen.state = "running"; screen.activeGame = true; }
+     }
+     Image{
+         id: pauseDialog
+         z: 1
+         source: "content/pics/pause.png"
+         anchors.centerIn: parent;
+         //opacity is deliberately not animated
+         opacity: 0 //Was !Qt.application.active && activeGame, but application doesn't work (QTBUG-23331)
+     }
+     Image {
+         Image {
+             id: title
+             source: "content/pics/snake.jpg"
+             fillMode: Image.PreserveAspectCrop
+             anchors.fill: parent
+             anchors.horizontalCenter: parent.horizontalCenter
+             anchors.verticalCenter: parent.verticalCenter
+             Column {
+                 spacing: 140
+                 anchors.verticalCenter: parent.verticalCenter;
+                 anchors.left:  parent.left;
+                 anchors.right:  parent.right;
+                 Text {
+                     color: "white"
+                     font.pointSize: 48
+                     font.italic: true;
+                     font.bold: true;
+                     text: "Snake"
+                     anchors.horizontalCenter: parent.horizontalCenter;
+                 }
+                 Text {
+                     color: "white"
+                     font.pointSize: 24
+                     anchors.horizontalCenter: parent.horizontalCenter;
+                     //horizontalAlignment: Text.AlignHCenter
+                     text: "Last Score:\t" + screen.lastScore + "\nHighscore:\t" + highScores.topScore;
+                 }
+             }
+         }
+         source: "content/pics/background.png"
+         fillMode: Image.PreserveAspectCrop
+         anchors.left: parent.left
+         anchors.right: parent.right
+         anchors.top: parent.top
+         anchors.bottom: toolbar.top
+         Rectangle {
+             id: playfield
+             border.width: 1
+             border.color: "white"
+             color: "transparent"
+             anchors.horizontalCenter: parent.horizontalCenter
+             y: (screen.height - 32 - height)/2;
+             width: screen.numColumnsAvailable * screen.gridSize + 2*screen.margin
+             height: screen.numRowsAvailable * screen.gridSize + 2*screen.margin
+             Content.Skull {
+                 id: skull
+             }
+             MouseArea {
+                 anchors.fill: parent
+                 onPressed: {
+                     if (screen.state == "") {
+                         Logic.startNewGame();
+                         return;
+                     }
+                     if (direction == 0 || direction == 2)
+                         Logic.scheduleDirection((mouseX > (head.x + head.width/2)) ? 1 : 3);
+                     else
+                         Logic.scheduleDirection((mouseY > (head.y + head.height/2)) ? 2 : 0);
+                 }
+             }
+         }
+     }
+     Rectangle {
+         id: progressBar
+         opacity: 0
+         Behavior on opacity { NumberAnimation { duration: 200 } }
+         color: "transparent"
+         border.width: 2
+         border.color: "#221edd"
+         x: 50
+         y: 50
+         width: 200
+         height: 30
+         anchors.horizontalCenter: parent.horizontalCenter
+         anchors.verticalCenter: parent.verticalCenter
+         anchors.verticalCenterOffset: 40
+         Rectangle {
+             id: progressIndicator
+             color: "#221edd";
+             width: 0;
+             height: 30;
+         }
+     }
+     Rectangle {
+         id: toolbar
+         color: activePalette.window
+         height: 32; width: parent.width
+         anchors.bottom: screen.bottom
+         Content.Button {
+             id: btnA; text: "New Game"; onClicked: Logic.startNewGame();
+             anchors.left: parent.left; anchors.leftMargin: 3
+             anchors.verticalCenter: parent.verticalCenter
+         }
+         Content.Button {
+             text: "Quit"
+             anchors { left: btnA.right; leftMargin: 3; verticalCenter: parent.verticalCenter }
+             onClicked: Qt.quit();
+         }
+         Text {
+             color: activePalette.text
+             text: "Score: " + screen.score; font.bold: true
+             anchors.right: parent.right; anchors.rightMargin: 3
+             anchors.verticalCenter: parent.verticalCenter
+         }
+     }
+     focus: true
+     Keys.onSpacePressed: Logic.startNewGame();
+     Keys.onLeftPressed: if (state == "starting" || direction != 1) Logic.scheduleDirection(3);
+     Keys.onRightPressed: if (state == "starting" || direction != 3) Logic.scheduleDirection(1);
+     Keys.onUpPressed: if (state == "starting" || direction != 2) Logic.scheduleDirection(0);
+     Keys.onDownPressed: if (state == "starting" || direction != 0) Logic.scheduleDirection(2);
+     states: [
+         State {
+             name: "starting"
+             PropertyChanges {target: progressIndicator; width: 200}
+             PropertyChanges {target: title; opacity: 0}
+             PropertyChanges {target: progressBar; opacity: 1}
+         },
+         State {
+             name: "running"
+             PropertyChanges {target: progressIndicator; width: 200}
+             PropertyChanges {target: title; opacity: 0}
+             PropertyChanges {target: skull; row: 0; column: 0; }
+             PropertyChanges {target: skull; spawned: 1}
+         }
+     ]
+     transitions: [
+         Transition {
+             from: "*"
+             to: "starting"
+             NumberAnimation { target: progressIndicator; property: "width"; duration: 1000 }
+             NumberAnimation { property: "opacity"; duration: 200 }
+         },
+         Transition {
+             to: "starting"
+             NumberAnimation { target: progressIndicator; property: "width"; duration: 1000 }
+             NumberAnimation { property: "opacity"; duration: 200 }
+         }
+     ]
+ }
+ }
index 0000000,064fd4b..353b993
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,90 +1,90 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: container
+     signal clicked
+     property string text
+     property bool keyUsing: false
+     BorderImage {
+         id: buttonImage
+         source: "images/toolbutton.sci"
+         width: container.width; height: container.height
+     }
+     BorderImage {
+         id: pressed
+         opacity: 0
+         source: "images/toolbutton.sci"
+         width: container.width; height: container.height
+     }
+     MouseArea {
+         id: mouseRegion
+         anchors.fill: buttonImage
+         onClicked: { container.clicked(); }
+     }
+     Text {
+         id: btnText
+         color: if(container.keyUsing){"#D0D0D0";} else {"#FFFFFF";}
+         anchors.centerIn: buttonImage; font.bold: true
+         text: container.text; style: Text.Raised; styleColor: "black"
+         font.pixelSize: 12
+     }
+     states: [
+         State {
+             name: "Pressed"
+             when: mouseRegion.pressed == true
+             PropertyChanges { target: pressed; opacity: 1 }
+         },
+         State {
+             name: "Focused"
+             when: container.activeFocus == true
+             PropertyChanges { target: btnText; color: "#FFFFFF" }
+         }
+     ]
+     transitions: Transition {
+         ColorAnimation { target: btnText; }
+     }
+ }
index 0000000,5fd0d16..4cb0dfc
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,105 +1,105 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Component {
+     id: listDelegate
+     Item {
+         id: wrapper; width: wrapper.ListView.view.width; height: if(txt.height > 60){txt.height+10}else{60} //50+5+5
+         function handleLink(link){
+             if(link.slice(0,3) == 'app'){
+                 screen.setUser(link.slice(7));
+             }else if(link.slice(0,4) == 'http'){
+                 Qt.openUrlExternally(link);
+             }
+         }
+         function addTags(str){
+             var ret = str.replace(/@[a-zA-Z0-9_]+/g, '<a href="app://$&">$&</a>');//click to jump to user?
+             var ret2 = ret.replace(/http:\/\/[^ \n\t]+/g, '<a href="$&">$&</a>');//surrounds http links with html link tags
+             return ret2;
+         }
+         // Strip away paranthesis
+         function userName(str) {
+             var user = str.replace(/\([\S|\s]*\)/gi, "");
+             return user.trim();
+         }
+         Item {
+             id: moveMe; height: parent.height
+             Rectangle {
+                 id: blackRect
+                 color: "black"; opacity: wrapper.ListView.index % 2 ? 0.2 : 0.3; height: wrapper.height-2; width: wrapper.width; y: 1
+             }
+             Item {
+                 id: image; x: 6; width: 48; height: 48; smooth: true
+                 anchors.verticalCenter: parent.verticalCenter
+                 Loading { x: 1; y: 1; width: 48; height: 48; visible: realImage.status != Image.Ready }
+                 Image {
+                     id: realImage;
+                     source: userImage; x: 1; y: 1;
+                     width:48; height:48; opacity:0 ;
+                     onStatusChanged: {
+                         if(status==Image.Ready)
+                             image.state="loaded"
+                     }
+                 }
+                 states: State {
+                     name: "loaded";
+                     PropertyChanges { target: realImage ; opacity:1 }
+                 }
+                 transitions: Transition { NumberAnimation { target: realImage; property: "opacity"; duration: 200 } }
+             }
+             Text { id:txt; y:4; x: 56
+                 text: '<html>'
+                     + '<a href="app://@'+userName(name)+'"><b>'+userName(name) + "</b></a> from " +source
+                     + "<br /><b>" + statusText + "</b></html>";
+                 textFormat: Text.StyledText
+                 color: "#cccccc"; style: Text.Raised; styleColor: "black"; wrapMode: Text.WordWrap; linkColor: "#aaccaa"
+                 anchors.left: image.right; anchors.right: blackRect.right; anchors.leftMargin: 6; anchors.rightMargin: 6
+                 onLinkActivated: wrapper.handleLink(link)
+             }
+         }
+     }
+ }
index 0000000,2987b9e..68b1c61
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,65 +1,65 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ FocusScope {
+     id:container
+     width: 220
+     height: 28
+     BorderImage { source: "images/lineedit.sci"; anchors.fill: parent }
+     signal accepted
+     property alias text: input.text
+     property alias item:input
+     TextInput{
+         id: input
+         width: parent.width - 12
+         anchors.centerIn: parent
+         maximumLength:21
+         font.pixelSize: 16;
+         font.bold: true
+         color: "#151515"; selectionColor: "mediumseagreen"
+         focus: true
+         onAccepted:{container.accepted()}
+         text: ""
+         selectByMouse: true
+     }
+ }
index 0000000,8f7c868..566857b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,49 +1,49 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Image {
+     id: loading; source: "images/loading.png"
+     NumberAnimation on rotation {
+         from: 0; to: 360; running: loading.visible == true; loops: Animation.Infinite; duration: 900
+     }
+ }
index 0000000,f52ce5b..3920520
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,60 +1,60 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     TitleBar { id: titleBar; width: parent.width; height: 60;
+         y: -80
+         untaggedString: "Latest tweets from everyone"
+         taggedString: "Latest tweets from "
+     }
+     states: [
+         State {
+             name: "search"; when: screen.state!="search"
+             PropertyChanges { target: titleBar; y: 0 }
+         }
+     ]
+     transitions: [
+         Transition { NumberAnimation { properties: "x,y"; duration: 500; easing.type: Easing.InOutQuad } }
+     ]
+ }
index 0000000,c405099..27f7495
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,80 +1,80 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.XmlListModel 2.0
+ Item { id: wrapper
+     property variant model: xmlModel
+     property string from : ""
+     property string to : ""
+     property string phrase : ""
+     property string mode : "everyone"
+     property int status: xmlModel.status
+     function reload() { xmlModel.reload(); }
+     XmlListModel {
+         id: xmlModel
+         function encodePhrase(x) { return encodeURIComponent(x); }
+         source: (from=="" && to=="" && phrase=="") ? "" :
+             'http://search.twitter.com/search.atom?from='+from+"&to="+to+"&phrase="+encodePhrase(phrase)
+         namespaceDeclarations: "declare default element namespace 'http://www.w3.org/2005/Atom'; " +
+                                "declare namespace twitter=\"http://api.twitter.com/\";";
+         query: "/feed/entry"
+         XmlRole { name: "statusText"; query: "content/string()" }
+         XmlRole { name: "timestamp"; query: "published/string()" }
+         XmlRole { name: "source"; query: "twitter:source/string()" }
+         XmlRole { name: "name"; query: "author/name/string()" }
+         XmlRole { name: "userImage"; query: "link[@rel = 'image']/@href/string()" }
+     }
+     Binding {
+         property: "mode"
+         target: wrapper
+         value: {if(wrapper.tags==''){"everyone";}else if(wrapper.tags=='my timeline'){"self";}else{"user";}}
+     }
+ }
index 0000000,82a8559..7732e6f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,124 +1,124 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ FocusScope {
+     id: wrapper
+     Column {
+         anchors.centerIn: parent
+         spacing: 20
+         Column{
+             spacing: 4
+             Text {
+                 text: "Posted by:"
+                 font.pixelSize: 16; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black"
+                 horizontalAlignment: Qt.AlignRight
+             }
+             Input{
+                 id: fromIn
+                 KeyNavigation.backtab: searchbutton
+                 KeyNavigation.tab:toIn
+                 onAccepted:searchbutton.doSearch();
+                 focus: true
+             }
+             Text {
+                 text: "In reply to:"
+                 font.pixelSize: 16; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black"
+                 horizontalAlignment: Qt.AlignRight
+             }
+             Input{
+                 id: toIn
+                 KeyNavigation.backtab: fromIn
+                 KeyNavigation.tab:phraseIn
+                 onAccepted:searchbutton.doSearch();
+             }
+             Text {
+                 text: "Search phrase:"
+                 font.pixelSize: 16; font.bold: true; color: "white"; style: Text.Raised; styleColor: "black"
+                 horizontalAlignment: Qt.AlignRight
+             }
+             Input{
+                 id: phraseIn
+                 KeyNavigation.backtab: toIn
+                 KeyNavigation.tab:searchbutton
+                 onAccepted:searchbutton.doSearch();
+                 text: "Qt Quick"
+             }
+         }
+         Button {
+             width: 100
+             height: 32
+             id: searchbutton
+             keyUsing: true;
+             opacity: 1
+             text: "Search"
+             KeyNavigation.tab: fromIn
+             Keys.onReturnPressed: searchbutton.doSearch();
+             Keys.onEnterPressed: searchbutton.doSearch();
+             Keys.onSelectPressed: searchbutton.doSearch();
+             Keys.onSpacePressed: searchbutton.doSearch();
+             onClicked: searchbutton.doSearch();
+             function doSearch() {
+                 // Search ! allowed
+                 if (wrapper.state=="invalidinput")
+                     return;
+                 rssModel.from=fromIn.text;
+                 rssModel.to= toIn.text;
+                 rssModel.phrase = phraseIn.text;
+                 screen.focus = true;
+                 screen.state = ""
+             }
+         }
+     }
+     states:
+     State {
+         name: "invalidinput"
+         when: fromIn.text=="" && toIn.text=="" && phraseIn.text==""
+         PropertyChanges { target: searchbutton ; opacity: 0.6 ; }
+     }
+     transitions:
+     Transition {
+         NumberAnimation { target: searchbutton; property: "opacity"; duration: 200 }
+     }
+ }
index 0000000,3624048..3e0818b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,130 +1,130 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: titleBar
+     property string untaggedString: "Uploads from everyone"
+     property string taggedString: "Recent uploads tagged "
+     BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
+     Item {
+         id: container
+         width: (parent.width * 2) - 55 ; height: parent.height
+         function accept() {
+             titleBar.state = ""
+             background.state = ""
+             rssModel.tags = editor.text
+         }
+         Item {
+             id:imageBox
+             x: 6; width: 0; height: 50; smooth: true
+             anchors.verticalCenter: parent.verticalCenter
+             UserModel { user: rssModel.from; id: userModel }
+             Component {
+                 id: imgDelegate;
+                 Item {
+                     id:imageitem
+                     visible:true
+                     Loading { width:48; height:48; visible: realImage.status != Image.Ready }
+                     Image { id: realImage; source: image; width:48; height:48; opacity:0; }
+                     states:
+                         State {
+                         name: "loaded"
+                         when:  (realImage.status == Image.Ready)
+                         PropertyChanges { target: realImage; opacity:1 }
+                     }
+                     transitions: Transition {
+                         NumberAnimation { target: realImage; property: "opacity"; duration: 200 }
+                     }
+                 }
+             }
+             ListView { id:view; model: userModel.model; x:1; y:1; delegate: imgDelegate }
+             states:
+             State {
+                 when: !userModel.user==""
+                 PropertyChanges { target: imageBox; width: 50; }
+             }
+             transitions:
+             Transition {
+                 NumberAnimation { target: imageBox; property: "width"; duration: 200 }
+             }
+         }
+         Image {
+             id: quitButton
+             x: 5
+             anchors.verticalCenter: parent.verticalCenter
+             source: "images/quit.png"
+             MouseArea {
+                 anchors.fill: parent
+                 onClicked: Qt.quit()
+             }
+         }
+         Text {
+             id: categoryText
+             anchors {
+                 left: quitButton.right; right: parent.right; leftMargin: 10; rightMargin: 10
+                 verticalCenter: parent.verticalCenter
+             }
+             elide: Text.ElideLeft
+             text: (rssModel.from=="" ? untaggedString : taggedString + rssModel.from)
+             font.bold: true; color: "White"; style: Text.Raised; styleColor: "Black"
+             font.pixelSize: 12
+         }
+     }
+     states: State {
+         name: "Tags"
+         PropertyChanges { target: container; x: -tagButton.x + 5 }
+         PropertyChanges { target: editor; focus: true }
+     }
+     transitions: Transition {
+         NumberAnimation { properties: "x"; easing.type: Easing.InOutQuad }
+     }
+ }
index 0000000,06d3324..d4265f3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,64 +1,64 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ Item {
+     id: toolbar
+     property alias button1Label: button1.text
+     property alias button2Label: button2.text
+     signal button1Clicked
+     signal button2Clicked
+     focus:true
+     BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
+     Button {
+         id: button1
+         anchors.left: parent.left; anchors.leftMargin: 5; y: 3; width: 140; height: 32
+         onClicked: toolbar.button1Clicked()
+         focus:true
+     }
+     Button {
+         id: button2
+         anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 140; height: 32
+         onClicked: toolbar.button2Clicked()
+     }
+ }
index 0000000,f88837c..428089b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,66 +1,66 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.XmlListModel 2.0
+ //This "model" gets the user information about the searched user. Mainly for the icon.
+ Item { id: wrapper
+     property variant model: xmlModel
+     property string user : ""
+     property int status: xmlModel.status
+     function reload() { xmlModel.reload(); }
+     XmlListModel {
+         id: xmlModel
+         source: user!= "" ? "http://twitter.com/users/show.xml?screen_name="+user : ""
+         query: "/user"
+         XmlRole { name: "name"; query: "name/string()" }
+         XmlRole { name: "screenName"; query: "screen_name/string()" }
+         XmlRole { name: "image"; query: "profile_image_url/string()" }
+         XmlRole { name: "location"; query: "location/string()" }
+         XmlRole { name: "description"; query: "description/string()" }
+         XmlRole { name: "followers"; query: "followers_count/string()" }
+         //TODO: Could also get the user's color scheme, timezone and a few other things
+     }
+ }
index 0000000,26e4a70..aca0968
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,135 +1,135 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ import QtQuick 2.0
+ import QtQuick.XmlListModel 2.0
+ import "TwitterCore" 2.0 as Twitter
+ Item {
+     id: screen; width: 320; height: 480
+     property bool userView : false
+     property variant tmpStr
+     function setUser(str){hack.running = true; tmpStr = str}
+     function reallySetUser(){rssModel.from = tmpStr;rssModel.to = ""; rssModel.phrase = ""}
+     state:"searchquery"
+     //Workaround for bug 260266
+     Timer{ interval: 1; running: false; repeat: false; onTriggered: screen.reallySetUser(); id:hack }
+     Keys.onEscapePressed: screen.state="searchquery"
+     Keys.onBacktabPressed: screen.state="searchquery"
+     Rectangle {
+         id: background
+         anchors.fill: parent; color: "#343434";
+         state:"searchquery"
+         Image { source: "TwitterCore/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 0.3 }
+         MouseArea {
+             anchors.fill: parent
+             onClicked: screen.focus = false;
+         }
+         Twitter.RssModel { id: rssModel }
+         Twitter.Loading { anchors.centerIn: parent; visible: rssModel.status==XmlListModel.Loading && state!='unauthed'}
+         Text {
+             width: 180
+             text: "Could not access twitter using this screen name and password pair.";
+             color: "#cccccc"; style: Text.Raised; styleColor: "black"; wrapMode: Text.WordWrap
+             visible: rssModel.status==XmlListModel.Error; anchors.centerIn: parent
+         }
+         Item {
+             id: views
+             x: 2; width: parent.width - 4
+             y:60 //Below the title bars
+             height: parent.height - 100
+             Text {
+                 id:title
+                 text: "Search Twitter"
+                 anchors.horizontalCenter: parent.horizontalCenter
+                 font.pixelSize: 20; font.bold: true; color: "#bbb"; style: Text.Raised; styleColor: "black"
+                 opacity:0
+             }
+             Twitter.SearchView{
+                 id: searchView
+                 anchors.verticalCenter: parent.verticalCenter
+                 width: parent.width; height: parent.height-60;
+                 x: -(screen.width * 1.5)
+             }
+             Twitter.FatDelegate { id: fatDelegate }
+             ListView {
+                 id: mainView; model: rssModel.model; delegate: fatDelegate;
+                 width: parent.width; height: parent.height; x: 0; cacheBuffer: 100;
+             }
+         }
+         Twitter.MultiTitleBar { id: titleBar; width: parent.width }
+         Twitter.ToolBar { id: toolBar; height: 40;
+             //anchors.bottom: parent.bottom;
+             //TODO: Use anchor changes instead of hard coding
+             y: screen.height - 40
+             width: parent.width; opacity: 0.9
+             button1Label: "New Search"
+             button2Label: "Update"
+             onButton1Clicked:
+             {
+                 screen.state="searchquery"
+             }
+             onButton2Clicked: rssModel.reload();
+         }
+     }
+     states: [
+         State {
+             name: "searchquery";
+             PropertyChanges { target: searchView; x: 0; focus:true}
+             PropertyChanges { target: mainView; x: -(parent.width * 1.5) }
+             PropertyChanges { target: titleBar; y: -80 }
+             PropertyChanges { target: toolBar; y: screen.height }
+             PropertyChanges { target: toolBar }
+             PropertyChanges { target: title; opacity:1}
+         }
+     ]
+     transitions: [
+         Transition { NumberAnimation { properties: "x,y,opacity"; duration: 500; easing.type: Easing.InOutQuad } }
+     ]
+ }
@@@ -1,3 -1,3 +1,3 @@@
  TEMPLATE = subdirs
- SUBDIRS += qml tutorials
 -SUBDIRS += demos shared localstorage particles qml qtquick tutorials window
++SUBDIRS += demos shared localstorage particles qml quick tutorials window
  contains(QT_CONFIG, qmltest): SUBDIRS += qmltest
@@@ -84,9 -84,10 +84,10 @@@ public
  //![1]
  
  
 -class ImageProviderExtensionPlugin : public QDeclarativeExtensionPlugin
 +class ImageProviderExtensionPlugin : public QQmlExtensionPlugin
  {
      Q_OBJECT
 -    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "imageprovider.json")
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "imageprovider.json")
  public:
      void registerTypes(const char *uri)
      {
  
  };
  
- #include "imageprovider.moc"
  
- Q_EXPORT_PLUGIN(ImageProviderExtensionPlugin);
 -#define QDeclarativeExtensionInterface_iid "org.qt-project.Qt.QDeclarativeExtensionInterface"
++#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface"
  
+ #include "imageprovider.moc"
@@@ -7,10 -7,12 +7,12 @@@ TARGET  = qmlimageproviderplugi
  
  SOURCES += imageprovider.cpp
  
+ OTHER_FILES += imageprovider.json
  sources.files = $$SOURCES imageprovider.qml imageprovider.pro
 -sources.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/declarative/imageprovider
 +sources.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/imageprovider
  
 -target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/declarative/imageprovider/ImageProviderCore
 +target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/imageprovider/ImageProviderCore
  
  ImageProviderCore_sources.files = \
      ImageProviderCore/qmldir 
@@@ -138,9 -138,11 +138,11 @@@ int TimeModel::instances=0
  MinuteTimer *TimeModel::timer=0;
  
  //![plugin]
 -class QExampleQmlPlugin : public QDeclarativeExtensionPlugin
 +class QExampleQmlPlugin : public QQmlExtensionPlugin
  {
      Q_OBJECT
 -    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "plugin.json")
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "plugin.json")
  public:
      void registerTypes(const char *uri)
      {
@@@ -15,11 -17,11 +17,11 @@@ qdeclarativesources.files += 
      com/nokia/TimeExample/hour.png \
      com/nokia/TimeExample/minute.png
  
- qqmlsources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/TimeExample
 -qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/declarative/plugins/com/nokia/TimeExample
++qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/TimeExample
  
  sources.files += plugins.pro plugin.cpp plugins.qml README
 -sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/declarative/plugins
 -target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/declarative/plugins/com/nokia/TimeExample
 +sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins
 +target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/TimeExample
  
- INSTALLS += qqmlsources sources target
+ INSTALLS += qdeclarativesources sources target
  
@@@ -69,9 -69,9 +69,9 @@@ void BirthdayParty::setHost(Person *c
      m_host = c;
  }
  
- QQmlListProperty<Person> BirthdayParty::guests() 
 -QDeclarativeListProperty<Person> BirthdayParty::guests() 
++QQmlListProperty<Person> BirthdayParty::guests()
  {
 -    return QDeclarativeListProperty<Person>(this, m_guests);
 +    return QQmlListProperty<Person>(this, m_guests);
  }
  
  int BirthdayParty::guestCount() const
@@@ -75,9 -75,9 +75,9 @@@ void BirthdayParty::setHost(Person *c
      emit hostChanged();
  }
  
- QQmlListProperty<Person> BirthdayParty::guests() 
 -QDeclarativeListProperty<Person> BirthdayParty::guests() 
++QQmlListProperty<Person> BirthdayParty::guests()
  {
 -    return QDeclarativeListProperty<Person>(this, m_guests);
 +    return QQmlListProperty<Person>(this, m_guests);
  }
  
  int BirthdayParty::guestCount() const
@@@ -54,9 -54,9 +54,9 @@@ void BirthdayParty::setHost(Person *c
      m_host = c;
  }
  
- QQmlListProperty<Person> BirthdayParty::guests() 
 -QDeclarativeListProperty<Person> BirthdayParty::guests() 
++QQmlListProperty<Person> BirthdayParty::guests()
  {
 -    return QDeclarativeListProperty<Person>(this, m_guests);
 +    return QQmlListProperty<Person>(this, m_guests);
  }
  
  int BirthdayParty::guestCount() const
@@@ -54,9 -54,9 +54,9 @@@ void BirthdayParty::setHost(Person *c
      m_host = c;
  }
  
- QQmlListProperty<Person> BirthdayParty::guests() 
 -QDeclarativeListProperty<Person> BirthdayParty::guests() 
++QQmlListProperty<Person> BirthdayParty::guests()
  {
 -    return QDeclarativeListProperty<Person>(this, m_guests);
 +    return QQmlListProperty<Person>(this, m_guests);
  }
  
  int BirthdayParty::guestCount() const
@@@ -54,9 -54,9 +54,9 @@@ void BirthdayParty::setHost(Person *c
      m_host = c;
  }
  
- QQmlListProperty<Person> BirthdayParty::guests() 
 -QDeclarativeListProperty<Person> BirthdayParty::guests() 
++QQmlListProperty<Person> BirthdayParty::guests()
  {
 -    return QDeclarativeListProperty<Person>(this, m_guests);
 +    return QQmlListProperty<Person>(this, m_guests);
  }
  
  int BirthdayParty::guestCount() const
@@@ -55,9 -55,9 +55,9 @@@ void BirthdayParty::setHost(Person *c
      m_host = c;
  }
  
- QQmlListProperty<Person> BirthdayParty::guests() 
 -QDeclarativeListProperty<Person> BirthdayParty::guests() 
++QQmlListProperty<Person> BirthdayParty::guests()
  {
 -    return QDeclarativeListProperty<Person>(this, m_guests);
 +    return QQmlListProperty<Person>(this, m_guests);
  }
  
  int BirthdayParty::guestCount() const
@@@ -55,9 -55,9 +55,9 @@@ void BirthdayParty::setHost(Person *c
      m_host = c;
  }
  
- QQmlListProperty<Person> BirthdayParty::guests() 
 -QDeclarativeListProperty<Person> BirthdayParty::guests() 
++QQmlListProperty<Person> BirthdayParty::guests()
  {
 -    return QDeclarativeListProperty<Person>(this, m_guests);
 +    return QQmlListProperty<Person>(this, m_guests);
  }
  
  int BirthdayParty::guestCount() const
@@@ -70,9 -70,9 +70,9 @@@ void BirthdayParty::setHost(Person *c
      m_host = c;
  }
  
- QQmlListProperty<Person> BirthdayParty::guests() 
 -QDeclarativeListProperty<Person> BirthdayParty::guests() 
++QQmlListProperty<Person> BirthdayParty::guests()
  {
 -    return QDeclarativeListProperty<Person>(this, m_guests);
 +    return QQmlListProperty<Person>(this, m_guests);
  }
  
  int BirthdayParty::guestCount() const
@@@ -70,9 -70,9 +70,9 @@@ void BirthdayParty::setHost(Person *c
      m_host = c;
  }
  
- QQmlListProperty<Person> BirthdayParty::guests() 
 -QDeclarativeListProperty<Person> BirthdayParty::guests() 
++QQmlListProperty<Person> BirthdayParty::guests()
  {
 -    return QDeclarativeListProperty<Person>(this, m_guests);
 +    return QQmlListProperty<Person>(this, m_guests);
  }
  
  int BirthdayParty::guestCount() const
index 0000000,0000000..2826161
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++TEMPLATE = app
++
++QT += quick qml
++SOURCES += main.cpp
++
++target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/accessibility
++qml.files = accessibility.qml content
++qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/accessibility
++INSTALLS += target qml
++
index 0000000,0000000..2804d2a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,110 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the QtQml module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "content"
++
++/*!
++    \title QtQuick Examples - Accessibility
++    \example qtquick/accessibility
++    \brief This example has accessible buttons.
++
++*/
++
++Rectangle {
++    id: window
++
++    width: 320; height: 480
++    color: "white"
++
++    Column {
++        id: column
++        spacing: 6
++        anchors.fill: parent
++        width: parent.width
++        Row {
++            spacing: 6
++            width: column.width
++            Button { width: 100; height: column.h + 20; text: "Send" }
++            Button { width: 100; height: column.h + 20; text: "Discard" }
++        }
++
++        Row {
++            spacing: 6
++            width: column.width
++            height: column.h
++            Text {
++                id: subjectLabel
++                Accessible.role: Accessible.StaticText
++                Accessible.name: text
++                text: "Subject:"
++            }
++            Rectangle {
++                id: subjectBorder
++                Accessible.role: Accessible.EditableText
++                Accessible.name: subjectEdit.text
++                border.width: 1
++                border.color: "black"
++                height: subjectEdit.height
++                width: 240
++                TextInput {
++                    id: subjectEdit
++                    text: "Vacation plans"
++                }
++            }
++        }
++        Rectangle {
++            id: textBorder
++            Accessible.role: Accessible.EditableText
++            property alias text : textEdit.text
++            border.width: 1
++            border.color: "black"
++            width: parent.width - 2
++            height: parent.height - (textBorder.y + column.spacing)
++            TextEdit {
++                id: textEdit
++                text: "Hi, we're going to the Dolomites this summer. Weren't you also going to northern Italy? \n\nbest wishes, your friend Luke"
++                width: parent.width
++                wrapMode: TextEdit.WordWrap
++            }
++        }
++    }
++}
index 0000000,0000000..2c203ab
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,80 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the QtQml module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: button
++
++    property bool checked: false
++    property alias text : buttonText.text
++    Accessible.name: text
++    Accessible.description: "This button does " + text
++    Accessible.role: Accessible.Button
++
++    signal clicked
++
++    width: buttonText.width + 20
++    height: 30
++    gradient: Gradient {
++        GradientStop { position: 0.0; color: "lightsteelblue" }
++        GradientStop { position: 1.0; color: "blue" }
++    }
++    border.width: 2
++    border.color: "black";
++    radius: 10
++
++    Text {
++        id: buttonText
++        text: parent.description
++        anchors.centerIn: parent
++        font.pixelSize: parent.height * .5
++        style: Text.Sunken; color: "white"; styleColor: "black"; smooth: true
++    }
++
++    MouseArea {
++        id: mouseArea
++        anchors.fill: parent
++        onClicked: {
++            checked = !checked;
++        }
++    }
++}
index 0000000,0000000..cdf83f8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++TEMPLATE = app
++
++QT += quick qml
++SOURCES += main.cpp
++
++target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/animation
++qml.files = animation.qml  basics  behaviors  easing pathanimation  pathinterpolator  states
++qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/animation
++INSTALLS += target qml
++
index 0000000,0000000..2e96daa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++import QmlProject 1.1
++
++Project {
++    mainFile: "animation.qml"
++
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..3d66d72
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..9407b2b
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..8270565
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..27ef924
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..7713ca5
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..4a4d3e3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,105 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id: window
++    width: 320; height: 480
++
++    // Let's draw the sky...
++    Rectangle {
++        anchors { left: parent.left; top: parent.top; right: parent.right; bottom: parent.verticalCenter }
++        gradient: Gradient {
++            GradientStop { position: 0.0; color: "DeepSkyBlue" }
++            GradientStop { position: 1.0; color: "LightSkyBlue" }
++        }
++    }
++
++    // ...and the ground.
++    Rectangle {
++        anchors { left: parent.left; top: parent.verticalCenter; right: parent.right; bottom: parent.bottom }
++        gradient: Gradient {
++            GradientStop { position: 0.0; color: "ForestGreen" }
++            GradientStop { position: 1.0; color: "DarkGreen" }
++        }
++    }
++
++    // The shadow for the smiley face
++    Image {
++        anchors.horizontalCenter: parent.horizontalCenter
++        y: smiley.minHeight + 58
++        source: "images/shadow.png"
++
++        // The scale property depends on the y position of the smiley face.
++        scale: smiley.y * 0.5 / (smiley.minHeight - smiley.maxHeight)
++    }
++
++    Image {
++        id: smiley
++        property int maxHeight: window.height / 3
++        property int minHeight: 2 * window.height / 3
++
++        anchors.horizontalCenter: parent.horizontalCenter
++        y: minHeight
++        source: "images/face-smile.png"
++
++        // Animate the y property. Setting loops to Animation.Infinite makes the
++        // animation repeat indefinitely, otherwise it would only run once.
++        SequentialAnimation on y {
++            loops: Animation.Infinite
++
++            // Move from minHeight to maxHeight in 300ms, using the OutExpo easing function
++            NumberAnimation {
++                from: smiley.minHeight; to: smiley.maxHeight
++                easing.type: Easing.OutExpo; duration: 300
++            }
++
++            // Then move back to minHeight in 1 second, using the OutBounce easing function
++            NumberAnimation {
++                from: smiley.maxHeight; to: smiley.minHeight
++                easing.type: Easing.OutBounce; duration: 1000
++            }
++
++            // Then pause for 500ms
++            PauseAnimation { duration: 500 }
++        }
++    }
++}
index 0000000,0000000..623c696
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,62 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: myRect
++
++    property string text
++
++    width: 75; height: 50
++    radius: 6
++    color: "#646464"
++    border.width: 4; border.color: "white"
++
++    MouseArea {
++        anchors.fill: parent
++        hoverEnabled: true
++        onEntered: {
++            focusRect.x = myRect.x; 
++            focusRect.y = myRect.y; 
++            focusRect.text = myRect.text;
++        }
++    }
++}
index 0000000,0000000..702b892
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,52 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++Image {
++    source: "quit.png"
++    scale: quitMouse.pressed ? 0.8 : 1.0
++    smooth: quitMouse.pressed
++    MouseArea {
++        id: quitMouse
++        anchors.fill: parent
++        anchors.margins: -10
++        onClicked: Qt.quit()
++    }
++}
index 0000000,0000000..b822057
new file mode 100644 (file)
Binary files differ
index 0000000,799dfd7..799dfd7
mode 000000,100644..100644
--- /dev/null
index 0000000,14ddf2a..14ddf2a
mode 000000,100644..100644
Binary files differ
index 0000000,0000000..7ca56a9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,101 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: page
++    width: 640; height: 480
++    color: "#343434"
++
++    Image { 
++        id: userIcon
++        x: topLeftRect.x; y: topLeftRect.y
++        source: "qt-logo.png"
++    }
++
++    Rectangle {
++        id: topLeftRect
++
++        anchors { left: parent.left; top: parent.top; leftMargin: 10; topMargin: 20 }
++        width: 46; height: 54
++        color: "Transparent"; border.color: "Gray"; radius: 6
++
++        // Clicking in here sets the state to the default state, returning the image to
++        // its initial position
++        MouseArea { anchors.fill: parent; onClicked: page.state = '' }
++    }
++
++    Rectangle {
++        id: middleRightRect
++
++        anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 20 }
++        width: 46; height: 54
++        color: "Transparent"; border.color: "Gray"; radius: 6
++
++        // Clicking in here sets the state to 'middleRight'
++        MouseArea { anchors.fill: parent; onClicked: page.state = 'middleRight' }
++    }
++
++    Rectangle {
++        id: bottomLeftRect
++
++        anchors { left: parent.left; bottom: parent.bottom; leftMargin: 10; bottomMargin: 20 }
++        width: 46; height: 54
++        color: "Transparent"; border.color: "Gray"; radius: 6
++
++        // Clicking in here sets the state to 'bottomLeft'
++        MouseArea { anchors.fill: parent; onClicked: page.state = 'bottomLeft' }
++    }
++
++    states: [
++        // In state 'middleRight', move the image to middleRightRect
++        State {
++            name: "middleRight"
++            PropertyChanges { target: userIcon; x: middleRightRect.x; y: middleRightRect.y }
++        },
++
++        // In state 'bottomLeft', move the image to bottomLeftRect
++        State {
++            name: "bottomLeft"
++            PropertyChanges { target: userIcon; x: bottomLeftRect.x; y: bottomLeftRect.y  }
++        }
++    ]
++}
index 0000000,0000000..d57924d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,130 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++/*
++    This is exactly the same as states.qml, except that we have appended
++    a set of transitions to apply animations when the item changes 
++    between each state.
++*/
++
++Rectangle {
++    id: page
++    width: 640; height: 480
++    color: "#343434"
++
++    Image { 
++        id: userIcon
++        x: topLeftRect.x; y: topLeftRect.y
++        source: "qt-logo.png"
++    }
++
++    Rectangle {
++        id: topLeftRect
++
++        anchors { left: parent.left; top: parent.top; leftMargin: 10; topMargin: 20 }
++        width: 46; height: 54
++        color: "Transparent"; border.color: "Gray"; radius: 6
++
++        // Clicking in here sets the state to the default state, returning the image to
++        // its initial position
++        MouseArea { anchors.fill: parent; onClicked: page.state = '' }
++    }
++
++    Rectangle {
++        id: middleRightRect
++
++        anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 20 }
++        width: 46; height: 54
++        color: "Transparent"; border.color: "Gray"; radius: 6
++
++        // Clicking in here sets the state to 'middleRight'
++        MouseArea { anchors.fill: parent; onClicked: page.state = 'middleRight' }
++    }
++
++    Rectangle {
++        id: bottomLeftRect
++
++        anchors { left: parent.left; bottom: parent.bottom; leftMargin: 10; bottomMargin: 20 }
++        width: 46; height: 54
++        color: "Transparent"; border.color: "Gray"; radius: 6
++
++        // Clicking in here sets the state to 'bottomLeft'
++        MouseArea { anchors.fill: parent; onClicked: page.state = 'bottomLeft' }
++    }
++
++    states: [
++        // In state 'middleRight', move the image to middleRightRect
++        State {
++            name: "middleRight"
++            PropertyChanges { target: userIcon; x: middleRightRect.x; y: middleRightRect.y }
++        },
++
++        // In state 'bottomLeft', move the image to bottomLeftRect
++        State {
++            name: "bottomLeft"
++            PropertyChanges { target: userIcon; x: bottomLeftRect.x; y: bottomLeftRect.y  }
++        }
++    ]
++
++    // Transitions define how the properties change when the item moves between each state
++    transitions: [
++
++        // When transitioning to 'middleRight' move x,y over a duration of 1 second,
++        // with OutBounce easing function.
++        Transition {
++            from: "*"; to: "middleRight"
++            NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce; duration: 1000 }
++        },
++
++        // When transitioning to 'bottomLeft' move x,y over a duration of 2 seconds,
++        // with InOutQuad easing function.
++        Transition {
++            from: "*"; to: "bottomLeft"
++            NumberAnimation { properties: "x,y"; easing.type: Easing.InOutQuad; duration: 2000 }
++        },
++
++        // For any other state changes move x,y linearly over duration of 200ms.
++        Transition {
++            NumberAnimation { properties: "x,y"; duration: 200 }
++        }
++    ]
++}
index 0000000,0000000..f57839b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,124 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "../contents"
++Item {
++  id:container
++  width:360
++  height:600
++
++  Column {
++    spacing:5
++    anchors.fill:parent
++    Text { font.pointSize:25; text:"Bezier Curve"; anchors.horizontalCenter:parent.horizontalCenter}
++
++    Canvas {
++      id:canvas
++      width:360
++      height:360
++      property string strokeStyle:"red"
++      property string fillStyle:"red"
++      property int lineWidth:lineWidthCtrl.value
++      property bool fill:true
++      property bool stroke:true
++      property real alpha:alphaCtrl.value
++      property real scaleX : scaleXCtrl.value
++      property real scaleY : scaleYCtrl.value
++      property real rotate : rotateCtrl.value
++      smooth:true
++      renderTarget:Canvas.Image
++      renderStrategy: Canvas.Immediate
++
++
++      Behavior on scaleX { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite } }
++      Behavior on scaleY { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} }
++      Behavior on rotate { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} }
++
++    onLineWidthChanged:requestPaint();
++    onFillChanged:requestPaint();
++    onStrokeChanged:requestPaint();
++    onAlphaChanged:requestPaint();
++    onScaleXChanged:requestPaint();
++    onScaleYChanged:requestPaint();
++    onRotateChanged:requestPaint();
++
++    onPaint: {
++      var ctx = canvas.getContext('2d');
++      ctx.save();
++      ctx.clearRect(0, 0, canvas.width, canvas.height);
++      ctx.globalAlpha = canvas.alpha;
++      ctx.strokeStyle = canvas.strokeStyle;
++      ctx.fillStyle = canvas.fillStyle;
++      ctx.lineWidth = canvas.lineWidth;
++      ctx.scale(canvas.scaleX, canvas.scaleY);
++      ctx.rotate(canvas.rotate);
++      ctx.beginPath();
++      ctx.moveTo(75,40);
++      ctx.bezierCurveTo(75,37,70,25,50,25);
++      ctx.bezierCurveTo(20,25,20,62.5,20,62.5);
++      ctx.bezierCurveTo(20,80,40,102,75,120);
++      ctx.bezierCurveTo(110,102,130,80,130,62.5);
++      ctx.bezierCurveTo(130,62.5,130,25,100,25);
++      ctx.bezierCurveTo(85,25,75,37,75,40);
++      ctx.closePath();
++      if (canvas.fill)
++         ctx.fill();
++      if (canvas.stroke)
++         ctx.stroke();
++      ctx.restore();
++    }
++  }
++
++    Rectangle {
++        id:controls
++        width:360
++        height:160
++        Column {
++          spacing:3
++          Slider {id:lineWidthCtrl; width:300; height:30; min:1; max:10; init:2; name:"Line width"}
++          Slider {id:scaleXCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleX"}
++          Slider {id:scaleYCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleY"}
++          Slider {id:rotateCtrl; width:300; height:30; min:0; max:Math.PI*2; init:0; name:"Rotate"}
++          Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"}
++        }
++    }
++  }
++}
index 0000000,0000000..d861ff0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,150 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "../contents"
++Item {
++  id:container
++  width:360
++  height:600
++
++  Column {
++    spacing:5
++    anchors.fill:parent
++    Text { font.pointSize:25; text:"Makes squircle icon with clip"; anchors.horizontalCenter:parent.horizontalCenter}
++    Canvas {
++      id:canvas
++      width:360
++      height:360
++      property string strokeStyle:"blue"
++      property string fillStyle:"steelblue"
++      property int lineWidth:2
++      property int nSize:nCtrl.value
++      property real radius:rCtrl.value
++      property bool fill:true
++      property bool stroke:false
++      property real px:xCtrl.value
++      property real py:yCtrl.value
++      property real alpha:alphaCtrl.value
++      property string imagefile:"../contents/qt-logo.png"
++      smooth:true
++      renderTarget:Canvas.Image
++      renderStrategy: Canvas.Immediate
++      Component.onCompleted:loadImage(canvas.imagefile);
++
++    onAlphaChanged:requestPaint();
++    onRadiusChanged:requestPaint();
++    onLineWidthChanged:requestPaint();
++    onNSizeChanged:requestPaint();
++    onFillChanged:requestPaint();
++    onStrokeChanged:requestPaint();
++    onPxChanged:requestPaint();
++    onPyChanged:requestPaint();
++    
++    onImageLoaded : requestPaint();
++
++    onPaint: squcirle();
++
++    function squcirle() {
++      var ctx = canvas.getContext("2d");
++      var N = canvas.nSize;
++      var R = canvas.radius;
++
++      N=Math.abs(N);
++      var M=N;
++      if (N>100) M=100;
++      if (N<0.00000000001) M=0.00000000001;
++
++      ctx.save();
++      ctx.globalAlpha =canvas.alpha;
++      ctx.fillStyle = "gray";
++      ctx.fillRect(0, 0, canvas.width, canvas.height);
++
++      ctx.strokeStyle = canvas.strokeStyle;
++      ctx.fillStyle = canvas.fillStyle;
++      ctx.lineWidth = canvas.lineWidth;
++
++      ctx.beginPath();
++      var i = 0, x, y;
++      for (i=0; i<(2*R+1); i++){
++         x = Math.round(i-R) + canvas.px;
++         y = Math.round(Math.pow(Math.abs(Math.pow(R,M)-Math.pow(Math.abs(i-R),M)),1/M)) + canvas.py;
++
++         if (i == 0)
++           ctx.moveTo(x, y);
++         else
++           ctx.lineTo(x, y);
++      }
++
++      for (i=(2*R); i<(4*R+1); i++){
++        x =Math.round(3*R-i)+canvas.px;
++        y = Math.round(-Math.pow(Math.abs(Math.pow(R,M)-Math.pow(Math.abs(3*R-i),M)),1/M)) + canvas.py;
++        ctx.lineTo(x, y);
++      }
++      ctx.closePath();
++      if (canvas.stroke) {
++          ctx.stroke();
++      }
++
++      if (canvas.fill) {
++          ctx.fill();
++      }
++      ctx.clip();
++
++      ctx.drawImage(canvas.imagefile, 0, 0);
++      ctx.restore();
++    }
++  }
++
++    Rectangle {
++        id:controls
++        width:360
++        height:160
++        Column {
++          spacing:3
++          Slider {id:nCtrl; width:300; height:30; min:1; max:10; init:4; name:"N"}
++          Slider {id:rCtrl; width:300; height:30; min:30; max:180; init:100; name:"Radius"}
++          Slider {id:xCtrl; width:300; height:30; min:50; max:300; init:180; name:"X"}
++          Slider {id:yCtrl; width:300; height:30; min:30; max:300; init:220; name:"Y"}
++          Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"}
++        }
++    }
++  }
++}
index 0000000,0000000..1413cdb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,87 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id: container
++
++    signal clicked
++
++    property string text
++    width: buttonText.width + 28
++    height: buttonText.height + 14
++
++    BorderImage {
++        id: buttonImage
++        source: "images/toolbutton.sci"
++        width: container.width - 10
++        height: container.height
++    }
++    BorderImage {
++        id: pressed
++        opacity: 0
++        source: "images/toolbutton.sci"
++        width: container.width - 10
++        height: container.height
++    }
++    MouseArea {
++        id: mouseRegion
++        anchors.fill: buttonImage
++        onClicked: { container.clicked(); }
++    }
++    Text {
++        id: buttonText
++        color: "white"
++        anchors.centerIn: buttonImage
++        font.bold: true
++        font.pointSize: 15
++        text: container.text
++        style: Text.Raised
++        styleColor: "black"
++    }
++    states: [
++        State {
++            name: "Pressed"
++            when: mouseRegion.pressed == true
++            PropertyChanges { target: pressed; opacity: 1 }
++        }
++    ]
++}
index 0000000,0000000..98b8efe
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,74 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the Qt Mobility Components.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id: scrollBar
++    // The properties that define the scrollbar's state.
++    // position and pageSize are in the range 0.0 - 1.0.  They are relative to the
++    // height of the page, i.e. a pageSize of 0.5 means that you can see 50%
++    // of the height of the view.
++    // orientation can be either 'Vertical' or 'Horizontal'
++    property real position
++    property real pageSize
++    property string orientation : "Vertical"
++    property alias bgColor: background.color
++    property alias fgColor: thumb.color
++
++    // A light, semi-transparent background
++    Rectangle {
++        id: background
++        radius: orientation == 'Vertical' ? (width/2 - 1) : (height/2 - 1)
++        color: "white"; opacity: 0.3
++        anchors.fill: parent
++    }
++    // Size the bar to the required size, depending upon the orientation.
++    Rectangle {
++        id: thumb
++        opacity: 0.7
++        color: "black"
++        radius: orientation == 'Vertical' ? (width/2 - 1) : (height/2 - 1)
++        x: orientation == 'Vertical' ? 1 : (scrollBar.position * (scrollBar.width-2) + 1)
++        y: orientation == 'Vertical' ? (scrollBar.position * (scrollBar.height-2) + 1) : 1
++        width: orientation == 'Vertical' ? (parent.width-2) : (scrollBar.pageSize * (scrollBar.width-2))
++        height: orientation == 'Vertical' ? (scrollBar.pageSize * (scrollBar.height-2)) : (parent.height-2)
++    }
++}
index 0000000,0000000..093b9e4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,115 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the QtQuick module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id:slider
++    property real min:0
++    property real max:1
++    property real value: min + (max - min) * (bar.x / (foo.width - bar.width))
++    property real init:min+(max-min)/2
++    property string name:"Slider"
++
++    Component.onCompleted: setValue(init)
++    function setValue(v) {
++       if (min < max)
++          bar.x = v/(max - min) * (foo.width - bar.width);
++    }
++    Rectangle {
++        id:sliderName
++        anchors.left:parent.left
++        height: childrenRect.height
++        width:childrenRect.width
++        anchors.verticalCenter:parent.verticalCenter
++        Text {
++           text:slider.name
++           font.pointSize:12
++         }
++    }
++    Item {
++        id: foo
++        height: 6
++        width: parent.width - 4 - sliderName.width
++        anchors.verticalCenter:parent.verticalCenter
++        anchors.left:sliderName.right
++        anchors.leftMargin:5
++        Rectangle {
++            height: parent.height
++            anchors.left: parent.left
++            anchors.right: bar.horizontalCenter
++            color: "blue"
++            radius: 3
++        }
++        Rectangle {
++            height: parent.height
++            anchors.left: bar.horizontalCenter
++            anchors.right: parent.right
++            color: "gray"
++            radius: 3
++        }
++        Rectangle {
++            anchors.fill: parent
++            color: "transparent"
++            radius: 3
++            border.width: 2
++            border.color: "black"
++        }
++
++        Rectangle {
++            id: bar
++            y: -7
++            width: 20
++            height: 20
++            radius: 15
++            color: "white"
++            border.width: 2
++            border.color: "black"
++            MouseArea {
++                anchors.fill: parent
++                drag.target: parent
++                drag.axis: Drag.XAxis
++                drag.minimumX: 0
++                drag.maximumX: foo.width - parent.width
++            }
++        }
++    }
++}
index 0000000,0000000..043bca1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,147 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++ListModel {
++    id:stocks
++    //Data from : http://en.wikipedia.org/wiki/NASDAQ-100
++
++    ListElement {name:"Activision Blizzard"; stockId:"ATVI"}
++    ListElement {name:"Adobe Systems Incorporated"; stockId:"ADBE"}
++    ListElement {name:"Akamai Technologies, Inc"; stockId:"AKAM"}
++    ListElement {name:"Alexion Pharmaceuticals"; stockId:"ALXN"}
++    ListElement {name:"Altera Corporation"; stockId:"ALTR"}
++    ListElement {name:"Amazon.com, Inc."; stockId:"AMZN"}
++    ListElement {name:"Amgen Inc."; stockId:"AMGN"}
++    ListElement {name:"Apollo Group, Inc."; stockId:"APOL"}
++    ListElement {name:"Apple Inc."; stockId:"AAPL"}
++    ListElement {name:"Applied Materials, Inc."; stockId:"AMAT"}
++    ListElement {name:"Autodesk, Inc."; stockId:"ADSK"}
++    ListElement {name:"Automatic Data Processing, Inc."; stockId:"ADP"}
++    ListElement {name:"Baidu.com, Inc."; stockId:"BIDU"}
++    ListElement {name:"Bed Bath & Beyond Inc."; stockId:"BBBY"}
++    ListElement {name:"Biogen Idec, Inc"; stockId:"BIIB"}
++    ListElement {name:"BMC Software, Inc."; stockId:"BMC"}
++    ListElement {name:"Broadcom Corporation"; stockId:"BRCM"}
++    ListElement {name:"C. H. Robinson Worldwide, Inc."; stockId:"CHRW"}
++    ListElement {name:"CA, Inc."; stockId:"CA"}
++    ListElement {name:"Celgene Corporation"; stockId:"CELG"}
++    ListElement {name:"Cephalon, Inc."; stockId:"CEPH"}
++    ListElement {name:"Cerner Corporation"; stockId:"CERN"}
++    ListElement {name:"Check Point Software Technologies Ltd."; stockId:"CHKP"}
++    ListElement {name:"Cisco Systems, Inc."; stockId:"CSCO"}
++    ListElement {name:"Citrix Systems, Inc."; stockId:"CTXS"}
++    ListElement {name:"Cognizant Technology Solutions Corporation"; stockId:"CTSH"}
++    ListElement {name:"Comcast Corporation"; stockId:"CMCSA"}
++    ListElement {name:"Costco Wholesale Corporation"; stockId:"COST"}
++    ListElement {name:"Ctrip.com International, Ltd."; stockId:"CTRP"}
++    ListElement {name:"Dell Inc."; stockId:"DELL"}
++    ListElement {name:"DENTSPLY International Inc."; stockId:"XRAY"}
++    ListElement {name:"DirecTV"; stockId:"DTV"}
++    ListElement {name:"Dollar Tree, Inc."; stockId:"DLTR"}
++    ListElement {name:"eBay Inc."; stockId:"EBAY"}
++    ListElement {name:"Electronic Arts Inc."; stockId:"ERTS"}
++    ListElement {name:"Expedia, Inc."; stockId:"EXPE"}
++    ListElement {name:"Expeditors International of Washington, Inc."; stockId:"EXPD"}
++    ListElement {name:"Express Scripts, Inc."; stockId:"ESRX"}
++    ListElement {name:"F5 Networks, Inc."; stockId:"FFIV"}
++    ListElement {name:"Fastenal Company"; stockId:"FAST"}
++    ListElement {name:"First Solar, Inc."; stockId:"FSLR"}
++    ListElement {name:"Fiserv, Inc."; stockId:"FISV"}
++    ListElement {name:"Flextronics International Ltd."; stockId:"FLEX"}
++    ListElement {name:"FLIR Systems, Inc."; stockId:"FLIR"}
++    ListElement {name:"Garmin Ltd."; stockId:"GRMN"}
++    ListElement {name:"Gilead Sciences, Inc."; stockId:"GILD"}
++    ListElement {name:"Google Inc."; stockId:"GOOG"}
++    ListElement {name:"Green Mountain Coffee Roasters, Inc."; stockId:"GMCR"}
++    ListElement {name:"Henry Schein, Inc."; stockId:"HSIC"}
++    ListElement {name:"Illumina, Inc."; stockId:"ILMN"}
++    ListElement {name:"Infosys Technologies"; stockId:"INFY"}
++    ListElement {name:"Intel Corporation"; stockId:"INTC"}
++    ListElement {name:"Intuit, Inc."; stockId:"INTU"}
++    ListElement {name:"Intuitive Surgical Inc."; stockId:"ISRG"}
++    ListElement {name:"Joy Global Inc."; stockId:"JOYG"}
++    ListElement {name:"KLA Tencor Corporation"; stockId:"KLAC"}
++    ListElement {name:"Lam Research Corporation"; stockId:"LRCX"}
++    ListElement {name:"Liberty Media Corporation, Interactive Series A"; stockId:"LINTA"}
++    ListElement {name:"Life Technologies Corporation"; stockId:"LIFE"}
++    ListElement {name:"Linear Technology Corporation"; stockId:"LLTC"}
++    ListElement {name:"Marvell Technology Group, Ltd."; stockId:"MRVL"}
++    ListElement {name:"Mattel, Inc."; stockId:"MAT"}
++    ListElement {name:"Maxim Integrated Products"; stockId:"MXIM"}
++    ListElement {name:"Microchip Technology Incorporated"; stockId:"MCHP"}
++    ListElement {name:"Micron Technology, Inc."; stockId:"MU"}
++    ListElement {name:"Microsoft Corporation"; stockId:"MSFT"}
++    ListElement {name:"Mylan, Inc."; stockId:"MYL"}
++    ListElement {name:"NetApp, Inc."; stockId:"NTAP"}
++    ListElement {name:"Netflix, Inc."; stockId:"NFLX"}
++    ListElement {name:"News Corporation, Ltd."; stockId:"NWSA"}
++    ListElement {name:"NII Holdings, Inc."; stockId:"NIHD"}
++    ListElement {name:"NVIDIA Corporation"; stockId:"NVDA"}
++    ListElement {name:"O'Reilly Automotive, Inc."; stockId:"ORLY"}
++    ListElement {name:"Oracle Corporation"; stockId:"ORCL"}
++    ListElement {name:"PACCAR Inc."; stockId:"PCAR"}
++    ListElement {name:"Paychex, Inc."; stockId:"PAYX"}
++    ListElement {name:"Priceline.com, Incorporated"; stockId:"PCLN"}
++    ListElement {name:"Qiagen N.V."; stockId:"QGEN"}
++    ListElement {name:"QUALCOMM Incorporated"; stockId:"QCOM"}
++    ListElement {name:"Research in Motion Limited"; stockId:"RIMM"}
++    ListElement {name:"Ross Stores Inc."; stockId:"ROST"}
++    ListElement {name:"SanDisk Corporation"; stockId:"SNDK"}
++    ListElement {name:"Seagate Technology Holdings"; stockId:"STX"}
++    ListElement {name:"Sears Holdings Corporation"; stockId:"SHLD"}
++    ListElement {name:"Sigma-Aldrich Corporation"; stockId:"SIAL"}
++    ListElement {name:"Staples Inc."; stockId:"SPLS"}
++    ListElement {name:"Starbucks Corporation"; stockId:"SBUX"}
++    ListElement {name:"Stericycle, Inc"; stockId:"SRCL"}
++    ListElement {name:"Symantec Corporation"; stockId:"SYMC"}
++    ListElement {name:"Teva Pharmaceutical Industries Ltd."; stockId:"TEVA"}
++    ListElement {name:"Urban Outfitters, Inc."; stockId:"URBN"}
++    ListElement {name:"VeriSign, Inc."; stockId:"VRSN"}
++    ListElement {name:"Vertex Pharmaceuticals"; stockId:"VRTX"}
++    ListElement {name:"Virgin Media, Inc."; stockId:"VMED"}
++    ListElement {name:"Vodafone Group, plc."; stockId:"VOD"}
++    ListElement {name:"Warner Chilcott, Ltd."; stockId:"WCRX"}
++    ListElement {name:"Whole Foods Market, Inc."; stockId:"WFM"}
++    ListElement {name:"Wynn Resorts Ltd."; stockId:"WYNN"}
++    ListElement {name:"Xilinx, Inc."; stockId:"XLNX"}
++    ListElement {name:"Yahoo! Inc."; stockId:"YHOO"}
++}
index 0000000,0000000..28edda2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,70 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id: titleBar
++    property string title: ""
++
++    BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
++
++    Image {
++        id: quitButton
++        anchors.left: parent.left//; anchors.leftMargin: 0
++        anchors.verticalCenter: parent.verticalCenter
++        source: "images/quit.png"
++        MouseArea {
++            anchors.fill: parent
++            onClicked: Qt.quit()
++        }
++    }
++
++    Text {
++        id: categoryText
++        anchors {
++            left: quitButton.right; right: parent.right; //leftMargin: 10; rightMargin: 10
++            verticalCenter: parent.verticalCenter
++        }
++        elide: Text.ElideLeft
++        text: title
++        font.bold: true; font.pointSize: 20; color: "White"; style: Text.Raised; styleColor: "Black"
++    }
++}
index 0000000,0000000..7ae7391
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,69 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id: toolbar
++
++    property variant labels
++    signal buttonClicked(int index)
++
++    BorderImage {
++        source: "images/titlebar.sci"
++        width: parent.width
++        height: parent.height + 14
++        y: -7
++    }
++
++    Row {
++        y: 3
++        anchors.horizontalCenter: parent.horizontalCenter
++        Repeater {
++            model: toolbar.labels
++            delegate:
++                Button {
++                    text: modelData
++                    onClicked: toolbar.buttonClicked(model.index)
++                }
++        }
++    }
++
++}
index 0000000,0000000..e434d32
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..56a63ce
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..248199c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,82 @@@
++<?xml version="1.0" encoding="UTF-8" standalone="no"?>
++<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="48px" height="48px" id="svg1306">
++  <defs id="defs1308">
++    <linearGradient id="linearGradient4083">
++      <stop id="stop4085" offset="0" stop-color="#ffffff" stop-opacity="0"/>
++      <stop offset="0.75" id="stop4089" stop-color="#ffffff" stop-opacity="0"/>
++      <stop id="stop4087" offset="1" stop-color="#ffffff" stop-opacity="1"/>
++    </linearGradient>
++    <linearGradient id="linearGradient4032">
++      <stop id="stop4034" offset="0" stop-color="#fff7c2" stop-opacity="0.63829786"/>
++      <stop offset="0.59394139" id="stop4036" stop-color="#fcaf3e" stop-opacity="0.18348624"/>
++      <stop id="stop4038" offset="0.83850551" stop-color="#fcaf3e" stop-opacity="0.50458717"/>
++      <stop id="stop4040" offset="1" stop-color="#fcaf3e" stop-opacity="1"/>
++    </linearGradient>
++    <linearGradient id="linearGradient4026">
++      <stop id="stop4028" offset="0" stop-color="#fff9c6" stop-opacity="1"/>
++      <stop offset="0.54166669" id="stop4042" stop-color="#fff28c" stop-opacity="1"/>
++      <stop id="stop4030" offset="1" stop-color="#ffea85" stop-opacity="1"/>
++    </linearGradient>
++    <linearGradient xlink:href="#linearGradient4026" id="linearGradient3168" gradientUnits="userSpaceOnUse" x1="-28.968945" y1="-25.326815" x2="-37.19698" y2="-9.5590506"/>
++    <radialGradient xlink:href="#linearGradient4032" id="radialGradient4020" cx="-33.519073" cy="-22.113297" fx="-33.519073" fy="-22.113297" r="9.5" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.487739,1.292402,-1.10267,0.497242,-41.77393,32.41492)"/>
++    <radialGradient xlink:href="#linearGradient4083" id="radialGradient4081" cx="23.99999" cy="23.381506" fx="23.99999" fy="23.381506" r="19.141981" gradientTransform="matrix(1.006701,2.235326e-16,-2.23715e-16,1.007522,-0.160816,0.426981)" gradientUnits="userSpaceOnUse"/>
++  </defs>
++  
++  <metadata id="metadata1311">
++    <rdf:RDF>
++      <cc:Work rdf:about="">
++        <dc:format>image/svg+xml</dc:format>
++        <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
++        <dc:title>weather-clear</dc:title>
++        <dc:date>January 2006</dc:date>
++        <dc:creator>
++          <cc:Agent>
++            <dc:title>Ryan Collier (pseudo)</dc:title>
++          </cc:Agent>
++        </dc:creator>
++        <dc:publisher>
++          <cc:Agent>
++            <dc:title>http://www.tango-project.org</dc:title>
++          </cc:Agent>
++        </dc:publisher>
++        <dc:source>http://www.pseudocode.org</dc:source>
++        <dc:subject>
++          <rdf:Bag>
++            <rdf:li>weather</rdf:li>
++            <rdf:li>applet</rdf:li>
++            <rdf:li>notification</rdf:li>
++          </rdf:Bag>
++        </dc:subject>
++        <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/"/>
++        <dc:contributor>
++          <cc:Agent>
++            <dc:title>Garrett LeSage</dc:title>
++          </cc:Agent>
++        </dc:contributor>
++      </cc:Work>
++      <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
++        <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
++        <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
++        <cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
++        <cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
++        <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
++        <cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
++      </cc:License>
++    </rdf:RDF>
++  </metadata>
++  <g id="layer1">
++    <g>
++      <g opacity="0.7">
++        <path d="M 24 2.5 L 21.625 9.1875 C 22.399034 9.0641318 23.191406 9 24 9 C 24.808594 9 25.600966 9.0641317 26.375 9.1875 L 24 2.5 z M 8.8125 8.78125 L 11.84375 15.21875 C 12.779034 13.928569 13.928569 12.779034 15.21875 11.84375 L 8.8125 8.78125 z M 39.21875 8.78125 L 32.78125 11.84375 C 34.071431 12.779034 35.220966 13.928569 36.15625 15.21875 L 39.21875 8.78125 z M 9.1875 21.59375 L 2.5 23.96875 L 9.1875 26.34375 C 9.0673373 25.57952 9 24.797813 9 24 C 9 23.180625 9.0608858 22.377571 9.1875 21.59375 z M 38.8125 21.625 C 38.935868 22.399034 39 23.191406 39 24 C 39 24.808594 38.935868 25.600966 38.8125 26.375 L 45.5 24 L 38.8125 21.625 z M 11.84375 32.78125 L 8.8125 39.1875 L 15.21875 36.15625 C 13.928569 35.220966 12.779034 34.071431 11.84375 32.78125 z M 36.15625 32.78125 C 35.229789 34.05926 34.087617 35.194799 32.8125 36.125 L 39.21875 39.1875 L 36.15625 32.78125 z M 21.625 38.8125 L 24 45.5 L 26.375 38.8125 C 25.600966 38.935868 24.808594 39 24 39 C 23.191406 39 22.399034 38.935868 21.625 38.8125 z " fill="#fce94f" fill-opacity="1" stroke="#fcaf3e" stroke-width="0.73732895" stroke-linecap="square" stroke-linejoin="miter" stroke-miterlimit="4" stroke-dasharray="none" stroke-opacity="1"/>
++        <path d="M 24 5.25 L 22.65625 9.0625 C 23.098888 9.0231486 23.547187 9 24 9 C 24.452813 9 24.901112 9.0231486 25.34375 9.0625 L 24 5.25 z M 10.78125 10.75 L 12.5 14.375 C 13.071538 13.694089 13.724004 13.038745 14.40625 12.46875 L 10.78125 10.75 z M 37.25 10.75 L 33.625 12.46875 C 34.304675 13.038189 34.961811 13.695325 35.53125 14.375 L 37.25 10.75 z M 9.0625 22.625 L 5.28125 23.96875 L 9.0625 25.3125 C 9.024981 24.880146 9 24.442031 9 24 C 9 23.536406 9.0212735 23.077908 9.0625 22.625 z M 38.9375 22.65625 C 38.976851 23.098888 39 23.547187 39 24 C 39 24.452813 38.976851 24.901112 38.9375 25.34375 L 42.71875 24 L 38.9375 22.65625 z M 35.53125 33.59375 C 34.958293 34.27954 34.309985 34.957363 33.625 35.53125 L 37.25 37.25 L 35.53125 33.59375 z M 12.5 33.625 L 10.78125 37.21875 L 14.375 35.5 C 13.702932 34.935884 13.064116 34.297068 12.5 33.625 z M 22.65625 38.9375 L 24 42.71875 L 25.34375 38.9375 C 24.901112 38.976851 24.452813 39 24 39 C 23.547187 39 23.098888 38.976851 22.65625 38.9375 z " fill="none" fill-opacity="1" stroke="url(#radialGradient4081)" stroke-width="0.84646249" stroke-linecap="square" stroke-linejoin="miter" stroke-miterlimit="4" stroke-dasharray="none" stroke-opacity="1"/>
++      </g>
++      <g>
++        <g>
++          <path transform="matrix(0.778062,-1.061285,1.061287,0.778062,67.47952,3.641324)" d="M -22.5 -17.5 A 9.5 9.5 0 1 1  -41.5,-17.5 A 9.5 9.5 0 1 1  -22.5 -17.5 z" fill="#ffee54" fill-opacity="1" stroke="#fcaf3e" stroke-width="0.75991178" stroke-linecap="square" stroke-linejoin="miter" stroke-miterlimit="4" stroke-dasharray="none" stroke-opacity="1"/>
++          <path transform="matrix(1.244257,-0.167707,0.216642,1.251844,67.61648,40.527)" d="M -22.5 -17.5 A 9.5 9.5 0 1 1  -41.5,-17.5 A 9.5 9.5 0 1 1  -22.5 -17.5 z" fill="url(#radialGradient4020)" fill-opacity="1" stroke="none" stroke-width="1.01737845" stroke-linecap="square" stroke-linejoin="miter" stroke-miterlimit="4" stroke-dasharray="none" stroke-opacity="1"/>
++          <path transform="matrix(0.715791,-0.976349,0.97635,0.715792,64.00044,5.269544)" d="M -22.5 -17.5 A 9.5 9.5 0 1 1  -41.5,-17.5 A 9.5 9.5 0 1 1  -22.5 -17.5 z" fill="none" fill-opacity="1" stroke="url(#linearGradient3168)" stroke-width="0.82601947" stroke-linecap="square" stroke-linejoin="miter" stroke-miterlimit="4" stroke-dasharray="none" stroke-opacity="1"/>
++        </g>
++      </g>
++    </g>
++  </g>
++</svg>
index 0000000,0000000..5d370cd
new file mode 100755 (executable)
Binary files differ
index 0000000,0000000..2cc38dc
new file mode 100755 (executable)
Binary files differ
index 0000000,0000000..054bff7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++border.left: 10
++border.top: 10
++border.bottom: 10
++border.right: 10
++source: lineedit.png
index 0000000,0000000..5bda1b6
new file mode 100755 (executable)
Binary files differ
index 0000000,0000000..9f36727
new file mode 100755 (executable)
Binary files differ
index 0000000,0000000..51c9008
new file mode 100755 (executable)
Binary files differ
index 0000000,0000000..0418d94
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++border.left: 10
++border.top: 12
++border.bottom: 12
++border.right: 10
++source: titlebar.png
index 0000000,0000000..1131001
new file mode 100755 (executable)
Binary files differ
index 0000000,0000000..9e4f965
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++border.left: 15
++border.top: 4
++border.bottom: 4
++border.right: 15
++source: toolbutton.png
index 0000000,0000000..5ab3a1b
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..bc3ca00
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,128 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "../contents"
++Item {
++  id:container
++  width:360
++  height:600
++
++  Column {
++    spacing:5
++    anchors.fill:parent
++    Text { font.pointSize:25; text:"Quadratic Curve"; anchors.horizontalCenter:parent.horizontalCenter}
++
++    Canvas {
++      id:canvas
++      width:360
++      height:360
++      property string strokeStyle:"steelblue"
++      property string fillStyle:"yellow"
++      property int lineWidth:lineWidthCtrl.value
++      property bool fill:true
++      property bool stroke:true
++      property real alpha:alphaCtrl.value
++      property real scaleX : scaleXCtrl.value
++      property real scaleY : scaleYCtrl.value
++      property real rotate : rotateCtrl.value
++      smooth:true
++      renderTarget:Canvas.Image
++      renderStrategy: Canvas.Immediate
++
++      onLineWidthChanged:requestPaint();
++      onFillChanged:requestPaint();
++      onStrokeChanged:requestPaint();
++      onAlphaChanged:requestPaint();
++      onScaleXChanged:requestPaint();
++      onScaleYChanged:requestPaint();
++      onRotateChanged:requestPaint();
++      Behavior on scaleX { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite } }
++      Behavior on scaleY { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} }
++      Behavior on rotate { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} }
++
++      onPaint: {
++          var ctx = canvas.getContext('2d');
++          ctx.save();
++          ctx.clearRect(0, 0, canvas.width, canvas.height);
++          ctx.globalAlpha = canvas.alpha;
++          ctx.strokeStyle = canvas.strokeStyle;
++          ctx.fillStyle = canvas.fillStyle;
++          ctx.lineWidth = canvas.lineWidth;
++          ctx.scale(canvas.scaleX, canvas.scaleY);
++          ctx.rotate(canvas.rotate);
++          ctx.beginPath();
++          ctx.moveTo(75,25);
++          ctx.quadraticCurveTo(25,25,25,62.5);
++          ctx.quadraticCurveTo(25,100,50,100);
++          ctx.quadraticCurveTo(50,120,30,125);
++          ctx.quadraticCurveTo(60,120,65,100);
++          ctx.quadraticCurveTo(125,100,125,62.5);
++          ctx.quadraticCurveTo(125,25,75,25);
++          ctx.closePath();
++          if (canvas.fill)
++             ctx.fill();
++          if (canvas.stroke)
++             ctx.stroke();
++
++
++          ctx.fillStyle="green";
++          ctx.font = "Bold 15px";
++
++          ctx.fillText("QML酷毙了", 30, 60);
++          ctx.restore();
++      }
++    }
++
++    Rectangle {
++        id:controls
++        width:360
++        height:160
++        Column {
++          spacing:3
++          Slider {id:lineWidthCtrl; width:300; height:30; min:1; max:10; init:2; name:"Line width"}
++          Slider {id:scaleXCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleX"}
++          Slider {id:scaleYCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleY"}
++          Slider {id:rotateCtrl; width:300; height:30; min:0; max:Math.PI*2; init:0; name:"Rotate"}
++          Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"}
++        }
++    }
++  }
++}
index 0000000,0000000..fd86c63
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,125 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "../contents"
++Item {
++  id:container
++  width:360
++  height:600
++
++  Column {
++    spacing:5
++    anchors.fill:parent
++    Text { font.pointSize:25; text:"Rounded rectangle"; anchors.horizontalCenter:parent.horizontalCenter}
++    Canvas {
++        id:canvas
++        width:360
++        height:360
++        smooth:true
++        renderTarget:Canvas.Image
++        renderStrategy: Canvas.Immediate
++
++        property int radius: rCtrl.value
++        property int rectx: rxCtrl.value
++        property int recty: ryCtrl.value
++        property int rectWidth: width - 2*rectx
++        property int rectHeight: height - 2*recty
++        property string strokeStyle:"blue"
++        property string fillStyle:"steelblue"
++        property int lineWidth:lineWidthCtrl.value
++        property bool fill:true
++        property bool stroke:true
++        property real alpha:alphaCtrl.value
++
++        onLineWidthChanged:requestPaint();
++        onFillChanged:requestPaint();
++        onStrokeChanged:requestPaint();
++        onRadiusChanged:requestPaint();
++        onRectxChanged:requestPaint();
++        onRectyChanged:requestPaint();
++        onAlphaChanged:requestPaint();
++
++        onPaint: {
++            var ctx = getContext("2d");
++            ctx.save();
++            ctx.clearRect(0,0,canvas.width, canvas.height);
++            ctx.strokeStyle = canvas.strokeStyle;
++            ctx.lineWidth = canvas.lineWidth
++            ctx.fillStyle = canvas.fillStyle
++            ctx.globalAlpha = canvas.alpha
++            ctx.beginPath();
++            ctx.moveTo(rectx+radius,recty);                 // top side
++            ctx.lineTo(rectx+rectWidth-radius,recty);
++            // draw top right corner
++            ctx.arcTo(rectx+rectWidth,recty,rectx+rectWidth,recty+radius,radius);
++            ctx.lineTo(rectx+rectWidth,recty+rectHeight-radius);    // right side
++            // draw bottom right corner
++            ctx.arcTo(rectx+rectWidth,recty+rectHeight,rectx+rectWidth-radius,recty+rectHeight,radius);
++            ctx.lineTo(rectx+radius,recty+rectHeight);              // bottom side
++            // draw bottom left corner
++            ctx.arcTo(rectx,recty+rectHeight,rectx,recty+rectHeight-radius,radius);
++            ctx.lineTo(rectx,recty+radius);                 // left side
++            // draw top left corner
++            ctx.arcTo(rectx,recty,rectx+radius,recty,radius);
++            ctx.closePath();
++            if (canvas.fill)
++                ctx.fill();
++            if (canvas.stroke)
++                ctx.stroke();
++            ctx.restore();
++        }
++    }
++
++    Rectangle {
++        id:controls
++        width:360
++        height:160
++        Column {
++          spacing:3
++          Slider {id:lineWidthCtrl; width:300; height:30; min:1; max:10; init:2; name:"Line width"}
++          Slider {id:rxCtrl; width:300; height:30; min:5; max:30; init:10; name:"rectx"}
++          Slider {id:ryCtrl; width:300; height:30; min:5; max:30; init:10; name:"recty"}
++          Slider {id:rCtrl; width:300; height:30; min:10; max:100; init:40; name:"Radius"}
++          Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"}
++        }
++    }
++  }
++}
index 0000000,0000000..28a48a6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,128 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "../contents"
++Item {
++  id:container
++  width:360
++  height:600
++
++  Column {
++    spacing:5
++    anchors.fill:parent
++    Text { font.pointSize:25; text:"Smile with arcs"; anchors.horizontalCenter:parent.horizontalCenter}
++
++    Canvas {
++        id:canvas
++        width:360
++        height:360
++        smooth:true
++        renderTarget:Canvas.Image
++        renderStrategy: Canvas.Immediate
++
++        property string strokeStyle:"green"
++        property string fillStyle:"yellow"
++        property int lineWidth:lineWidthCtrl.value
++        property bool fill:true
++        property bool stroke:true
++        property real alpha:alphaCtrl.value
++        property real scaleX : scaleXCtrl.value
++        property real scaleY : scaleYCtrl.value
++        property real rotate : rotateCtrl.value
++
++        onLineWidthChanged:requestPaint();
++        onFillChanged:requestPaint();
++        onStrokeChanged:requestPaint();
++        onAlphaChanged:requestPaint();
++        onScaleXChanged:requestPaint();
++        onScaleYChanged:requestPaint();
++        onRotateChanged:requestPaint();
++
++        Behavior on scaleX { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite } }
++        Behavior on scaleY { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} }
++        Behavior on rotate { SpringAnimation { spring: 2; damping: 0.2; loops:Animation.Infinite} }
++
++    onPaint: {
++          var ctx = canvas.getContext('2d');
++          ctx.save();
++          ctx.clearRect(0, 0, canvas.width, canvas.height);
++          ctx.globalAlpha = canvas.alpha;
++          ctx.strokeStyle = canvas.strokeStyle;
++          ctx.fillStyle = canvas.fillStyle;
++          ctx.lineWidth = canvas.lineWidth;
++          ctx.scale(canvas.scaleX, canvas.scaleY);
++          ctx.rotate(canvas.rotate);
++          ctx.beginPath();
++          ctx.moveTo(75 + 50  * Math.cos(0),
++                     75 - 50  * Math.sin(Math.PI*2));
++          ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle
++          ctx.moveTo(75,70);
++          ctx.arc(75,70,35,0,Math.PI,false);   // Mouth (clockwise)
++          ctx.moveTo(60,65);
++          ctx.arc(60,65,5,0,Math.PI*2,true);  // Left eye
++          ctx.moveTo(90 + 5  * Math.cos(0),
++                     65 - 5  * Math.sin(Math.PI*2));
++          ctx.moveTo(90,65);
++          ctx.arc(90,65,5,0,Math.PI*2,true);  // Right eye
++          ctx.closePath();
++          if (canvas.fill)
++             ctx.fill();
++          if (canvas.stroke)
++             ctx.stroke();
++          ctx.restore();
++        }
++    }
++
++    Rectangle {
++        id:controls
++        width:360
++        height:160
++        Column {
++          spacing:3
++          Slider {id:lineWidthCtrl; width:300; height:30; min:1; max:10; init:2; name:"Line width"}
++          Slider {id:scaleXCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleX"}
++          Slider {id:scaleYCtrl; width:300; height:30; min:0.1; max:10; init:1; name:"ScaleY"}
++          Slider {id:rotateCtrl; width:300; height:30; min:0; max:Math.PI*2; init:0; name:"Rotate"}
++          Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"}
++        }
++    }
++  }
++}
index 0000000,0000000..86c69d9
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..2fc65b6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,155 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "../contents"
++Item {
++  id:container
++  width:360
++  height:600
++
++  Column {
++    spacing:5
++    anchors.fill:parent
++    Text { font.pointSize:25; text:"Squircles"; anchors.horizontalCenter:parent.horizontalCenter}
++    Image {
++       anchors.horizontalCenter:parent.horizontalCenter
++       source:"squircle.png"
++       width:250
++       height:25
++    }
++    Canvas {
++        id:canvas
++        width:360
++        height:360
++        smooth:true
++        renderTarget:Canvas.Image
++        renderStrategy: Canvas.Immediate
++
++        property string strokeStyle:"blue"
++        property string fillStyle:"steelblue"
++        property int lineWidth:2
++        property int nSize:nCtrl.value
++        property real radius:rCtrl.value
++        property bool fill:true
++        property bool stroke:false
++        property real px:xCtrl.value
++        property real py:yCtrl.value
++        property real alpha:alphaCtrl.value
++
++        onAlphaChanged:requestPaint();
++        onRadiusChanged:requestPaint();
++        onLineWidthChanged:requestPaint();
++        onNSizeChanged:requestPaint();
++        onFillChanged:requestPaint();
++        onStrokeChanged:requestPaint();
++        onPxChanged:requestPaint();
++        onPyChanged:requestPaint();
++
++
++        onPaint: squcirle();
++
++        function squcirle() {
++          var ctx = canvas.getContext("2d");
++          var N = canvas.nSize;
++          var R = canvas.radius;
++
++          N=Math.abs(N);
++          var M=N;
++          if (N>100) M=100;
++          if (N<0.00000000001) M=0.00000000001;
++
++          ctx.save();
++          ctx.globalAlpha =canvas.alpha;
++          ctx.fillStyle = "gray";
++          ctx.fillRect(0, 0, canvas.width, canvas.height);
++
++          ctx.strokeStyle = canvas.strokeStyle;
++          ctx.fillStyle = canvas.fillStyle;
++          ctx.lineWidth = canvas.lineWidth;
++
++          ctx.beginPath();
++          var i = 0, x, y;
++          for (i=0; i<(2*R+1); i++){
++             x = Math.round(i-R) + canvas.px;
++             y = Math.round(Math.pow(Math.abs(Math.pow(R,M)-Math.pow(Math.abs(i-R),M)),1/M)) + canvas.py;
++
++             if (i == 0)
++               ctx.moveTo(x, y);
++             else
++               ctx.lineTo(x, y);
++          }
++
++          for (i=(2*R); i<(4*R+1); i++){
++            x =Math.round(3*R-i)+canvas.px;
++            y = Math.round(-Math.pow(Math.abs(Math.pow(R,M)-Math.pow(Math.abs(3*R-i),M)),1/M)) + canvas.py;
++            ctx.lineTo(x, y);
++          }
++          ctx.closePath();
++          if (canvas.stroke) {
++              ctx.stroke();
++          }
++
++          if (canvas.fill) {
++              ctx.fill();
++          }
++
++          ctx.fillStyle = "yellow";
++          ctx.font = "Helvetica  16px";
++          ctx.fillText("|X-" + Math.round(canvas.px) + "|^" + N + " + |Y-"+Math.round(canvas.py)+"|^" + N + " = |" + Math.round(R) + "|^" + N, canvas.px - 125, canvas.py);
++          ctx.restore();
++        }
++    }
++
++    Rectangle {
++        id:controls
++        width:360
++        height:160
++        Column {
++          spacing:3
++          Slider {id:nCtrl; width:300; height:30; min:1; max:10; init:4; name:"N"}
++          Slider {id:rCtrl; width:300; height:30; min:30; max:180; init:100; name:"Radius"}
++          Slider {id:xCtrl; width:300; height:30; min:50; max:300; init:180; name:"X"}
++          Slider {id:yCtrl; width:300; height:30; min:30; max:300; init:220; name:"Y"}
++          Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"}
++        }
++    }
++  }
++}
index 0000000,0000000..2652866
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++To run:
++
++  make install
++  QML_IMPORT_PATH=$PWD qmlscene stock.qml
++
index 0000000,0000000..4c60e55
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1 @@@
++plugin qmlstockchartexampleplugin
index 0000000,0000000..42eb2d5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,255 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++#include "model.h"
++
++#include <QtCore/QUrl>
++#include <QtCore/QDate>
++#include <QtCore/QList>
++#include <QtCore/QStringList>
++#include <QtCore/QDebug>
++
++#include <QtNetwork/QNetworkAccessManager>
++#include <QtNetwork/QNetworkReply>
++
++StockModel::StockModel(QObject *parent)
++    : QAbstractListModel(parent)
++    , _startDate(QDate(1995, 4, 25))
++    , _endDate(QDate::currentDate())
++    , _dataCycle(StockModel::Daily)
++    , _manager(0)
++    , _updating(false)
++{
++    QHash<int, QByteArray> roles;
++    roles[StockModel::DateRole] = "date";
++    roles[StockModel::SectionRole] = "year";
++    roles[StockModel::OpenPriceRole] = "openPrice";
++    roles[StockModel::ClosePriceRole] = "closePrice";
++    roles[StockModel::HighPriceRole] = "highPrice";
++    roles[StockModel::LowPriceRole] = "lowPrice";
++    roles[StockModel::VolumeRole] = "volume";
++    roles[StockModel::AdjustedPriceRole] = "adjustedPrice";
++    setRoleNames(roles);
++
++    connect(this, SIGNAL(stockNameChanged()), SLOT(requestData()));
++    connect(this, SIGNAL(startDateChanged()), SLOT(requestData()));
++    connect(this, SIGNAL(endDateChanged()), SLOT(requestData()));
++    connect(this, SIGNAL(dataCycleChanged()), SLOT(requestData()));
++
++    _manager = new QNetworkAccessManager(this);
++    connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(update(QNetworkReply*)));
++
++}
++
++int StockModel::rowCount(const QModelIndex & parent) const {
++    Q_UNUSED(parent);
++    return _prices.count();
++}
++
++StockPrice* StockModel::stockPriceAtIndex(int idx) const
++{
++    if (idx >=0 && idx < _prices.size()) {
++        return _prices[idx];
++    }
++    return 0;
++}
++
++
++void StockModel::requestData()
++{
++    if (!_updating) {
++        _updating = true;
++        QMetaObject::invokeMethod(this, "doRequest", Qt::QueuedConnection);
++    }
++}
++
++void StockModel::doRequest()
++{
++    /*
++        Fetch stock data from yahoo finance:
++         url: http://ichart.finance.yahoo.com/table.csv?s=NOK&a=5&b=11&c=2010&d=7&e=23&f=2010&g=d&ignore=.csv
++            s:stock name/id, a:start day, b:start month, c:start year  default: 25 April 1995, oldest c= 1962
++            d:end day, e:end month, f:end year, default:today  (data only available 3 days before today)
++            g:data cycle(d daily,  w weekly, m monthly, v Dividend)
++      */
++    if (_manager && !_stockName.isEmpty() && _endDate > _startDate) {
++        QString query("http://ichart.finance.yahoo.com/table.csv?s=%1&a=%2&b=%3&c=%4&d=%5&e=%6&f=%7&g=%8&ignore=.csv");
++        query = query.arg(_stockName)
++                     .arg(_startDate.day()).arg(_startDate.month()).arg(_startDate.year())
++                     .arg(_endDate.day()).arg(_endDate.month()).arg(_endDate.year())
++                     .arg(dataCycleString());
++
++        qDebug() << "request stock data:" << query;
++        QNetworkReply* reply = _manager->get(QNetworkRequest(QUrl(query)));
++        connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SIGNAL(downloadProgress(qint64,qint64)));
++    }
++}
++
++void StockModel::update(QNetworkReply *reply)
++{
++    _updating = false;
++
++    if (reply) {
++         if (reply->error() == QNetworkReply::NoError) {
++            beginResetModel();
++
++            foreach (StockPrice* p, _prices) {
++                p->deleteLater();
++            }
++
++            _prices.clear();
++
++            while (!reply->atEnd()) {
++                QString line = reply->readLine();
++                QStringList fields = line.split(',');
++
++                //data format:Date,Open,High,Low,Close,Volume,Adjusted close price
++                //example: 2011-06-24,6.03,6.04,5.88,5.88,20465200,5.88
++                if (fields.size() == 7) {
++                    StockPrice* price = new StockPrice(this);
++                    price->setDate(QDate::fromString(fields[0], Qt::ISODate));
++                    price->setOpenPrice(fields[1].toFloat());
++                    price->setHighPrice(fields[2].toFloat());
++                    price->setLowPrice(fields[3].toFloat());
++                    price->setClosePrice(fields[4].toFloat());
++                    price->setVolume(fields[5].toInt());
++                    price->setAdjustedPrice(fields[6].toFloat());
++                    _prices.prepend(price);
++                }
++            }
++            qDebug() << "get stock data successfully, total:" << _prices.count() << "records.";
++         } else {
++            qDebug() << "get stock data failed:" << reply->errorString();
++         }
++         reply->deleteLater();
++         endResetModel();
++         emit dataChanged(QModelIndex(), QModelIndex());
++    }
++}
++
++QVariant StockModel::data(const QModelIndex & index, int role) const {
++    if (index.row() < 0 || index.row() > _prices.count())
++        return QVariant();
++
++    const StockPrice* price = _prices[index.row()];
++    if (role == StockModel::DateRole)
++        return price->date();
++    else if (role == StockModel::OpenPriceRole)
++        return price->openPrice();
++    else if (role == StockModel::ClosePriceRole)
++        return price->closePrice();
++    else if (role == StockModel::HighPriceRole)
++        return price->highPrice();
++    else if (role == StockModel::LowPriceRole)
++        return price->lowPrice();
++    else if (role == StockModel::AdjustedPriceRole)
++        return price->adjustedPrice();
++    else if (role == StockModel::VolumeRole)
++        return price->volume();
++    else if (role == StockModel::SectionRole)
++        return price->date().year();
++    return QVariant();
++}
++
++QString StockModel::stockName() const
++{
++    return _stockName;
++}
++void StockModel::setStockName(const QString& name)
++{
++    if (_stockName != name) {
++        _stockName = name;
++        emit stockNameChanged();
++    }
++}
++
++QDate StockModel::startDate() const
++{
++    return _startDate;
++}
++void StockModel::setStartDate(const QDate& date)
++{
++    if (_startDate.isValid() && _startDate != date) {
++        _startDate = date;
++        emit startDateChanged();
++    }
++}
++
++QDate StockModel::endDate() const
++{
++    return _endDate;
++}
++void StockModel::setEndDate(const QDate& date)
++{
++    if (_endDate.isValid() && _endDate != date) {
++        _endDate = date;
++        emit endDateChanged();
++    }
++}
++
++StockModel::StockDataCycle StockModel::dataCycle() const
++{
++    return _dataCycle;
++}
++
++QString StockModel::dataCycleString() const
++{
++    switch (_dataCycle) {
++    case StockModel::Daily:
++        return QString('d');
++        break;
++    case StockModel::Weekly:
++        return QString('w');
++    case StockModel::Monthly:
++        return QString('m');
++    case StockModel::Dividend:
++        return QString('v');
++    }
++
++    return QString('d');
++}
++
++
++void StockModel::setDataCycle(StockModel::StockDataCycle cycle)
++{
++    if (_dataCycle != cycle) {
++        _dataCycle = cycle;
++        emit dataCycleChanged();
++    }
++}
index 0000000,0000000..95e6f48
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,166 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++#include <QtCore/QAbstractListModel>
++#include <QtCore/QDate>
++
++class StockPrice : public QObject
++{
++    Q_OBJECT
++    Q_PROPERTY(QDate date READ date)
++    Q_PROPERTY(qreal openPrice READ openPrice)
++    Q_PROPERTY(qreal closePrice READ closePrice)
++    Q_PROPERTY(qreal highPrice READ highPrice)
++    Q_PROPERTY(qreal lowPrice READ lowPrice)
++    Q_PROPERTY(qint32 volume READ volume)
++    Q_PROPERTY(qreal adjustedPrice READ adjustedPrice)
++public:
++
++    StockPrice(QObject *parent = 0)
++        : QObject(parent)
++        , _openPrice(-1)
++        , _closePrice(-1)
++        , _highPrice(-1)
++        , _lowPrice(-1)
++        , _volume(-1)
++        , _adjustedPrice(-1)
++    {
++    }
++    QDate date() const {return _date;}
++    qreal openPrice() const {return _openPrice; }
++    qreal closePrice() const {return _closePrice;}
++    qreal highPrice() const {return _highPrice;}
++    qreal lowPrice() const{return _lowPrice;}
++    qreal adjustedPrice() const{return _adjustedPrice;}
++    qint32 volume() const{return _volume;}
++
++    void setDate(const QDate& date){_date = date;}
++    void setOpenPrice(qreal price){_openPrice = price;}
++    void setClosePrice(qreal price){_closePrice = price;}
++    void setHighPrice(qreal price){_highPrice = price;}
++    void setLowPrice(qreal price){_lowPrice = price;}
++    void setAdjustedPrice(qreal price) {_adjustedPrice = price;}
++    void setVolume(qint32 volume) {_volume = volume;}
++
++private:
++    QDate _date;
++    qreal _openPrice;
++    qreal _closePrice;
++    qreal _highPrice;
++    qreal _lowPrice;
++    qint32 _volume;
++    qreal _adjustedPrice;
++};
++
++class QNetworkReply;
++class QNetworkAccessManager;
++class StockModel : public QAbstractListModel
++{
++    Q_OBJECT
++
++    Q_PROPERTY(QString stockName READ stockName WRITE setStockName NOTIFY stockNameChanged)
++    Q_PROPERTY(QDate startDate READ startDate WRITE setStartDate NOTIFY startDateChanged)
++    Q_PROPERTY(QDate endDate READ endDate WRITE setEndDate NOTIFY endDateChanged)
++    Q_PROPERTY(StockDataCycle dataCycle READ dataCycle WRITE setDataCycle NOTIFY dataCycleChanged)
++
++    Q_ENUMS(StockDataCycle)
++public:
++    enum StockDataCycle {
++        Daily,
++        Weekly,
++        Monthly,
++        Dividend
++    };
++
++    enum StockModelRoles {
++        DateRole = Qt::UserRole + 1,
++        SectionRole,
++        OpenPriceRole,
++        ClosePriceRole,
++        HighPriceRole,
++        LowPriceRole,
++        VolumeRole,
++        AdjustedPriceRole
++    };
++
++    StockModel(QObject *parent = 0);
++
++    QString stockName() const;
++    void setStockName(const QString& name);
++
++    QDate startDate() const;
++    void setStartDate(const QDate& date);
++
++    QDate endDate() const;
++    void setEndDate(const QDate& date);
++
++    StockDataCycle dataCycle() const;
++    void setDataCycle(StockDataCycle cycle);
++
++    int rowCount(const QModelIndex & parent = QModelIndex()) const;
++
++    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
++
++signals:
++    void stockNameChanged();
++    void startDateChanged();
++    void endDateChanged();
++    void dataCycleChanged();
++    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
++
++public slots:
++    void requestData();
++    StockPrice* stockPriceAtIndex(int idx) const;
++private slots:
++    void doRequest();
++    void update(QNetworkReply* reply);
++private:
++    QString dataCycleString() const;
++    QList<StockPrice*> _prices;
++    QString _stockName;
++    QDate _startDate;
++    QDate _endDate;
++    StockDataCycle _dataCycle;
++    QNetworkAccessManager* _manager;
++    bool _updating;
++};
++
++
++
++
index 0000000,0000000..3b354e2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,60 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <QtQml/QQmlExtensionPlugin>
++#include <QtQml/qqml.h>
++#include <QtGui/QGuiApplication>
++#include "model.h"
++
++class QStockChartExampleQmlPlugin : public QQmlExtensionPlugin
++{
++    Q_OBJECT
++public:
++    void registerTypes(const char *uri)
++    {
++        Q_ASSERT(uri == QLatin1String("com.nokia.StockChartExample"));
++        qmlRegisterType<StockModel>(uri, 1, 0, "StockModel");
++        qmlRegisterType<StockPrice>(uri, 1, 0, "StockPrice");
++    }
++};
++
++#include "plugin.moc"
++
++Q_EXPORT_PLUGIN2(qmlstockchartexampleplugin, QStockChartExampleQmlPlugin);
index 0000000,0000000..1c95fde
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,726 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++import QtQuick 2.0
++import com.nokia.StockChartExample 1.0
++import "../contents"
++
++Rectangle {
++    id:container
++    width: 360; height: 600
++    color: "#343434";
++    Image { source: "contents/images/stripes.png"; fillMode: Image.Tile; anchors.fill: parent; opacity: 1 }
++
++
++    TitleBar {
++        id: titleBar
++        width: parent.width
++        anchors.top : container.top
++        height: 40
++        opacity: 0.9
++    }
++
++    StockModel {
++        id:stockModel
++        dataCycle: StockModel.Daily
++        function dataCycleName() {
++            if (dataCycle === StockModel.Weekly)
++                return "Weekly";
++            else if (dataCycle === StockModel.Monthly)
++                return "Monthly";
++            return "Daily";
++        }
++
++        onDataChanged: {
++            if (view.viewType == "chart") {
++                canvas.requestPaint();
++            }
++        }
++        onDownloadProgress: {
++            if (bytesReceived == bytesTotal && bytesTotal != -1) {
++                progress.opacity = 0;
++            } else {
++                progress.opacity = 0.8;
++                progress.text = "downloading " + stockModel.dataCycleName() + " data ..."+ Math.round(bytesReceived/1000) + " KB";
++            }
++        }
++
++        property string description:"";
++    }
++
++    Stocks {id:stocks}
++
++    Rectangle {
++        id: header
++        width: parent.width
++        height: 20
++        color: "steelblue"
++        opacity: 0
++        Row {
++            spacing: 2
++            Text {
++                id:t
++                font.pointSize:15
++                horizontalAlignment:Text.AlignHCenter
++                font.bold: true
++                font.underline:true
++            }
++            Rectangle {
++              height:20
++              width:50
++              Text {text:"Stock list"; font.pointSize:15; font.bold: true}
++            }
++        }
++    }
++
++    ListView {
++        id:stockList
++        width: parent.width
++        anchors.bottom: container.bottom
++        anchors.top : titleBar.bottom
++        focus: true
++        keyNavigationWraps: true
++        spacing:1
++        opacity: 1
++        model: stocks
++
++        Component.onCompleted: opacity = 0.9;
++        onOpacityChanged: {
++            titleBar.title = "Top 100 NASDAQ stocks"
++        }
++
++
++        delegate : Rectangle {
++                height: 30
++                width: view.width
++                color: {
++                    if (ListView.isCurrentItem)
++                        return focus ? "lightyellow" : "pink";
++                    return index % 2 == 0 ? "lightblue" : "lightsteelblue"
++                }
++                Text {
++                       font.pointSize:20
++                       text: index + ". " + stockId + " \t(" + name + ")";
++                }
++                MouseArea {
++                    anchors.fill: parent;
++                    onDoubleClicked: {
++                        stockList.opacity = 0;
++                        stockModel.stockName = stockId;
++                        stockModel.description = "NASDAQ:" + stockId + " (" + name + ")";
++                        view.opacity = 1;
++                        view.viewType = "chart";
++                        canvas.opacity = 0.7;
++                    }
++                    onClicked: stockList.currentIndex = index
++                }//mousearea
++        }//delegate
++    }
++
++    ListView {
++        id:view
++        width: container.width
++        height: container.height - 50
++        anchors.bottom: container.bottom
++        focus: true
++        keyNavigationWraps: true
++
++        spacing:1
++        opacity: 0
++        model: stockModel
++        highlightFollowsCurrentItem: false
++        highlightRangeMode: ListView.StrictlyEnforceRange
++        preferredHighlightBegin:50
++        preferredHighlightEnd : height - 50
++        highlight: listHighlight
++
++        //header : Text {}
++        delegate: listDelegate
++        snapMode: ListView.SnapToItem
++
++        property string viewType : "list"
++        property int topIndex:indexAt(0,contentY);
++        property int bottomIndex:indexAt(0, contentY+height);
++
++        onCountChanged:  {
++
++            titleBar.title = stockModel.description + " " + Qt.formatDate(stockModel.startDate, "yyyy-MM-dd") + " - " +
++                    Qt.formatDate(stockModel.endDate, "yyyy-MM-dd") + " " + stockModel.dataCycleName() +
++                             " records:" + view.count;
++
++        }
++
++        Component {
++            id: listDelegate
++            Rectangle {
++                height: 20
++                width: view.width
++                border.color: "lightsteelblue"
++                border.width: 1
++                color: {
++                    if (ListView.isCurrentItem)
++                        return focus ? "lightyellow" : "pink";
++
++                    return index % 2 == 0 ? "lightblue" : "lightsteelblue"
++                }
++                Text {
++                       font.pointSize:13
++                       text: index + ". " + Qt.formatDate(date, "yyyy-MM-dd")
++                             + "\t " + Math.round(openPrice*100)/100
++                             + "\t " + Math.round(highPrice*100)/100
++                             + "\t " + Math.round(lowPrice*100)/100
++                             + "\t " + Math.round(closePrice*100)/100
++                             + "\t " + volume + "\t "
++                             + Math.round(adjustedPrice*100)/100;
++                }
++                MouseArea {anchors.fill: parent; onClicked: view.currentIndex = index}
++            }
++        }
++
++        Component {
++            id: chartDelegate
++            Rectangle {
++                height: 20
++                width: view.width/view.count * canvas.scaleX
++                border.color: "lightsteelblue"
++                border.width: 1
++                color: {
++                    if (ListView.isCurrentItem)
++                        return focus ? "lightyellow" : "pink";
++
++                    return index % 2 == 0 ? "lightblue" : "lightsteelblue"
++                }
++
++                Text {
++                    anchors.bottom: parent.bottom
++                    font.pointSize: {
++                        if (parent.width <= 4)
++                            return  1;
++                        if (parent.width <= 50)
++                            return parent.width/4;
++                        return 15;
++                    }
++                    horizontalAlignment:Text.AlignHCenter
++                    verticalAlignment:Text.AlignBottom
++                    text:font.pointSize > 1 ? Qt.formatDate(date, "d/M/yy") : ""
++                }
++                MouseArea {anchors.fill: parent; onClicked: view.currentIndex = index}
++            }
++        }
++
++        Component {
++            id:chartHighlight
++            Rectangle { radius: 5; width:40; height: 20; color: "lightsteelblue" }
++        }
++
++        Component {
++            id:listHighlight
++            Rectangle { radius: 5; width:container.width; height: 20; color: "lightsteelblue" }
++        }
++
++
++
++
++        onViewTypeChanged : {
++            if (viewType == "list") {
++                view.orientation = ListView.Vertical;
++                view.delegate = listDelegate;
++//                view.section.property = "year";
++//                view.section.criteria = ViewSection.FullString;
++//                view.section.delegate = sectionHeading;
++                view.highlight = listHighlight;
++                view.opacity = 1;
++                canvas.opacity = 0;
++               // comment.opacity = 0;
++
++            } else if (viewType == "chart") {
++                view.orientation = ListView.Horizontal;
++                view.delegate = chartDelegate;
++                //comment.opacity = 0.6;
++
++                view.opacity = 1;
++                view.height = 30
++
++                canvas.opacity = 0.7;
++                canvas.requestPaint();
++            } else {
++                viewType = "list";
++            }
++        }
++
++
++        onCurrentIndexChanged: {
++            //header.updateCurrent(stockModel.stockPriceAtIndex(view.currentIndex));
++            if (viewType == "chart") {
++                canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX);
++                canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX);
++
++                canvas.requestPaint();
++            }
++        }
++        onContentYChanged: {    // keep "current" item visible
++            topIndex = indexAt(0,contentY);
++            bottomIndex = indexAt(0, contentY+height);
++
++            if (topIndex != -1 && currentIndex <= topIndex)
++                currentIndex = topIndex+1;
++            else if (bottomIndex != -1 && currentIndex >= bottomIndex)
++                currentIndex = bottomIndex-1;
++            if (viewType == "chart")
++                canvas.requestPaint();
++        }
++
++        onContentXChanged: {    // keep "current" item visible
++            topIndex = indexAt(contentX,0);
++            bottomIndex = indexAt(contentX+width, 0);
++
++            if (topIndex != -1 && currentIndex <= topIndex)
++                currentIndex = topIndex+1;
++            else if (bottomIndex != -1 && currentIndex >= bottomIndex)
++                currentIndex = bottomIndex-1;
++            if (viewType == "chart")
++                canvas.requestPaint();
++        }
++
++        MouseArea {
++            anchors.fill: parent
++            onDoubleClicked: {
++                if (view.viewType == "list")
++                    view.viewType = "chart";
++                else
++                    view.viewType = "list";
++            }
++        }
++    }
++
++
++
++    Canvas {
++        id:canvas
++        anchors.top : titleBar.bottom
++        anchors.bottom : view.top
++        width:container.width;
++        opacity:0
++        renderTarget: Canvas.Image
++        renderStrategy: Canvas.Immediate
++        property bool running:false
++        property int frames:first
++        property int mouseX:0;
++        property int mouseY:0;
++        property int mousePressedX:0;
++        property int mousePressedY:0;
++        property int movedY:0
++        property real scaleX:1.0;
++        property real scaleY:1.0;
++        property int first:0;
++        property int last:view.count - 1;
++
++        onOpacityChanged: {
++            if (opacity > 0)
++                requestPaint();
++        }
++        Text {
++           id:comment
++           x:100
++           y:50
++           font.pointSize: 20
++           color:"white"
++           opacity: 0.7
++           focus:false
++           text: stockModel.description
++           function updateCurrent(price)
++           {
++               if (price !== undefined) {
++                   text =stockModel.description + "\n"
++                           + Qt.formatDate(price.date, "yyyy-MM-dd") + " OPEN:"
++                           + Math.round(price.openPrice*100)/100 + " HIGH:"
++                           + Math.round(price.highPrice*100)/100 + " LOW:"
++                           + Math.round(price.lowPrice*100)/100 + " CLOSE:"
++                           + Math.round(price.closePrice*100)/100 + " VOLUME:"
++                           + price.volume;
++               }
++           }
++        }
++
++        Text {
++            id:priceAxis
++            x:25
++            y:25
++            font.pointSize: 15
++            color:"yellow"
++            opacity: 0.7
++            focus: false
++        }
++        Text {
++            id:volumeAxis
++            x:canvas.width - 200
++            y:25
++            font.pointSize: 15
++            color:"yellow"
++            opacity: 0.7
++        }
++
++        Rectangle {
++            id:progress
++            x:canvas.width/2 - 100
++            y:canvas.height/2
++            width:childrenRect.width
++            height: childrenRect.height
++            opacity: 0
++            color:"white"
++            property string text;
++            Text {
++                text:parent.text
++                font.pointSize: 20
++            }
++        }
++
++        Button {
++            id:runButton
++            text:"Run this chart"
++            y:0
++            x:canvas.width/2 - 50
++            opacity: 0.5
++            onClicked:  {
++                if (canvas.running) {
++                    canvas.running = false;
++                    canvas.frames = canvas.first;
++                    canvas.requestPaint();
++                    text = "Run this chart";
++                    comment.text = stockModel.description;
++                } else {
++                    text = " Stop running ";
++                    canvas.runChart();
++                }
++            }
++        }
++        Button {
++            id:returnButton
++            text:"Stocks"
++            y:0
++            anchors.left : runButton.right
++            anchors.leftMargin : 20
++            opacity: 0.5
++            onClicked:  {
++                stockList.opacity = 1;
++                canvas.opacity = 0;
++            }
++        }
++        PinchArea {
++            anchors.fill: parent
++            onPinchUpdated : {
++                var current = pinch.center;
++                var scale = pinch.scale;
++                console.log("center:" + pinch.center + " scale:" + pinch.scale);
++                //canvas.requestPaint();
++            }
++        }
++
++        MouseArea {
++            anchors.fill: parent
++
++            onDoubleClicked: {
++                if (stockModel.dataCycle == StockModel.Daily)
++                    stockModel.dataCycle = StockModel.Weekly;
++                else if (stockModel.dataCycle == StockModel.Weekly)
++                    stockModel.dataCycle = StockModel.Monthly;
++                else
++                    stockModel.dataCycle = StockModel.Daily;
++            }
++
++            onPositionChanged: {
++                if (mouse.modifiers & Qt.ControlModifier) {
++                    if (canvas.mouseX == 0 && canvas.mouseY == 0) {
++                        canvas.mouseX = mouse.x;
++                        canvas.mouseY = mouse.y;
++                    }
++                } else{
++                    var w = (view.width/view.count)*canvas.scaleX;
++
++                    //canvas.movedY += Math.round((canvas.mousePressedY - mouse.y)/2);
++
++                    var movedX = Math.round((canvas.mousePressedX - mouse.x)/w);
++                    if (movedX != 0 || canvas.movedY != 0) {
++                        if (canvas.first + movedX >= 0 && canvas.last + movedX < view.count) {
++                            canvas.first += movedX;
++                            canvas.last += movedX;
++                        }
++                        canvas.requestPaint();
++                    }
++                }
++            }
++
++            onPressed:  {
++                canvas.mousePressedX = mouse.x;
++                canvas.mousePressedY = mouse.y;
++            }
++
++            onReleased : {
++                if (mouse.modifiers & Qt.ControlModifier) {
++                    var sx = mouse.x - canvas.mouseX;
++                    var sy = canvas.mouseY - mouse.y;
++
++                    if (Math.abs(sx) < 50) sx = 0;
++                    if (Math.abs(sy) < 50) sy = 0;
++
++                    if (sx > 0)
++                        canvas.scaleX *= sx/100 +1;
++                    else
++                        canvas.scaleX *= 1/(-sx/100 + 1);
++
++                    if (sy > 0)
++                        canvas.scaleY *= sy/100 +1;
++                    else
++                        canvas.scaleY *= 1/(-sy/100 + 1);
++
++                    if (canvas.scaleX < 1)
++                        canvas.scaleX = 1;
++
++                    //console.log("scaleX:" + canvas.scaleX + ", scaleY:" + canvas.scaleY);
++
++                    canvas.first = Math.round(view.currentIndex - view.currentIndex / canvas.scaleX);
++                    canvas.last = Math.round(view.currentIndex + (view.count - view.currentIndex) / canvas.scaleX);
++
++                    canvas.mouseX = 0;
++                    canvas.mouseY = 0;
++                    canvas.mousePressedX = 0;
++                    canvas.mousePressedY = 0;
++                    canvas.requestPaint();
++                }
++            }
++        }
++
++        function runChart() {
++           canvas.running = true;
++            requestPaint();
++        }
++
++        function showPriceAt(x) {
++            var w = (view.width/view.count)*canvas.scaleX;
++            //header.updateCurrent(stockModel.stockPriceAtIndex(canvas.first + Math.round(x/w)));
++            //console.log("x:" + x + " w:" + w + " index:" + (canvas.first + Math.round(x/w)));
++        }
++
++        function drawPrice(ctx, from, to, color, price, points, highest)
++        {
++            ctx.globalAlpha = 0.7;
++            ctx.strokeStyle = color;
++            ctx.lineWidth = 1;
++            ctx.beginPath();
++
++            //price x axis
++            priceAxis.text = "price:" + Math.round(highest);
++            ctx.font = "bold 12px sans-serif";
++
++            ctx.strokeText("price", 25, 25);
++            for (var j = 1; j < 30; j++) {
++                var val = (highest * j) / 30;
++                val = canvas.height * (1 - val/highest);
++                ctx.beginPath();
++
++                ctx.moveTo(10, val);
++                if (j % 5)
++                    ctx.lineTo(15, val);
++                else
++                    ctx.lineTo(20, val);
++                ctx.stroke();
++            }
++
++            ctx.beginPath();
++            ctx.moveTo(10, 0);
++            ctx.lineTo(10, canvas.height);
++            ctx.stroke();
++
++
++            var w = canvas.width/points.length;
++            var end = canvas.running? canvas.frames - canvas.first :points.length;
++            for (var i = 0; i < end; i++) {
++                var x = points[i].x;
++                var y = points[i][price];
++                y += canvas.movedY;
++
++                y = canvas.height * (1 - y/highest);
++                if (i == 0) {
++                    ctx.moveTo(x+w/2, y);
++                } else {
++                    ctx.lineTo(x+w/2, y);
++                }
++            }
++            ctx.stroke();
++        }
++
++        function drawKLine(ctx, from, to, points, highest)
++        {
++            ctx.globalAlpha = 0.4;
++            ctx.lineWidth = 2;
++            var end = canvas.running? canvas.frames - canvas.first :points.length;
++            for (var i = 0; i < end; i++) {
++                var x = points[i].x;
++                var open = canvas.height * (1 - points[i].open/highest) - canvas.movedY;
++                var close = canvas.height * (1 - points[i].close/highest) - canvas.movedY;
++                var high = canvas.height * (1 - points[i].high/highest) - canvas.movedY;
++                var low = canvas.height * (1 - points[i].low/highest) - canvas.movedY;
++
++                var top, bottom;
++                if (close <= open) {
++                    ctx.fillStyle = Qt.rgba(1, 0, 0, 1);
++                    ctx.strokeStyle = Qt.rgba(1, 0, 0, 1);
++                    top = close;
++                    bottom = open;
++                } else {
++                    ctx.fillStyle = Qt.rgba(0, 1, 0, 1);
++                    ctx.strokeStyle = Qt.rgba(0, 1, 0, 1);
++                    top = open;
++                    bottom = close;
++                }
++
++                var w1, w2;
++                w1 = canvas.width/points.length;
++                w2 = w1 > 10 ? w1/2 : w1;
++
++                ctx.fillRect(x + (w1 - w2)/2, top, w2, bottom - top);
++                ctx.beginPath();
++                ctx.moveTo(x+w1/2, high);
++                ctx.lineTo(x+w1/2, low);
++                ctx.stroke();
++            }
++            ctx.globalAlpha = 1;
++
++        }
++
++        function drawVolume(ctx, from, to, color, price, points, highest)
++        {
++            ctx.fillStyle = color;
++            ctx.globalAlpha = 0.6;
++            ctx.strokeStyle = Qt.rgba(0.8, 0.8, 0.8, 1);
++            ctx.lineWidth = 1;
++
++            //volume x axis
++            volumeAxis.text = "volume:" + Math.round(highest/(1000*100))  + "M";
++            for (var j = 1; j < 30; j++) {
++                var val = (highest * j) / 30;
++                val = canvas.height * (1 - val/highest);
++                ctx.beginPath();
++                if (j % 5)
++                    ctx.moveTo(canvas.width - 15, val);
++                else
++                    ctx.moveTo(canvas.width - 20, val);
++                ctx.lineTo(canvas.width - 10, val);
++                ctx.stroke();
++            }
++
++            ctx.beginPath();
++            ctx.moveTo(canvas.width - 10, 0);
++            ctx.lineTo(canvas.width - 10, canvas.height);
++            ctx.stroke();
++
++            var end = canvas.running? canvas.frames - canvas.first :points.length;
++            for (var i = 0; i < end; i++) {
++                var x = points[i].x;
++                var y = points[i][price];
++                y = canvas.height * (1 - y/highest);
++                ctx.fillRect(x, y, canvas.width/points.length, canvas.height - y);
++            }
++        }
++/*
++        onPainted : {
++            if (canvas.running) {
++                if (frames >= last) {
++                    canvas.running = false;
++                    canvas.frames = first;
++                    runButton.text = "Run this chart";
++                    comment.text = stockModel.description;
++                    requestPaint();
++                } else {
++                    frames += Math.round(view.count / 100);
++                    if (frames > last) frames = last;
++                    var price = stockModel.stockPriceAtIndex(frames);
++                    if (price) {
++                        comment.updateCurrent(price);
++                    }
++
++                    requestPaint();
++                }
++            }
++        }
++*/
++        onPaint: {
++            if (view.currentIndex <= 0)
++                first = 0;
++            if (last >= view.count)
++                last = view.count - 1;
++
++            //console.log("painting...  first:" + first + ", last:" + last + " current:" + view.currentIndex);
++            var ctx = canvas.getContext("2d");
++            ctx.save();
++
++            ctx.globalCompositeOperation = "source-over";
++            ctx.lineWidth = 1;
++            ctx.lineJoin = "round";
++            ctx.fillStyle = "rgba(0,0,0,0)";
++
++            ctx.fillRect(0, 0, canvas.width, canvas.height);
++
++
++
++            var highestPrice = 500/canvas.scaleY;
++            var highestValume = 600 * 1000 * 1000/canvas.scaleY;
++            var points = [];
++            for (var i = 0; i <= last - first; i++) {
++                var price = stockModel.stockPriceAtIndex(i + first);
++                points.push({
++                             x: i*canvas.width/(last-first+1),
++                             open: price.openPrice,
++                             close: price.closePrice,
++                             high:price.highPrice,
++                             low:price.lowPrice,
++                             volume:price.volume
++                            });
++            }
++
++            drawPrice(ctx, first, last, Qt.rgba(1, 0, 0, 1),"high", points, highestPrice);
++            drawPrice(ctx, first, last, Qt.rgba(0, 1, 0, 1),"low", points, highestPrice);
++            drawPrice(ctx, first, last, Qt.rgba(0, 0, 1, 1),"open", points, highestPrice);
++            drawPrice(ctx, first, last, Qt.rgba(0.5, 0.5, 0.5, 1),"close", points, highestPrice);
++            drawVolume(ctx, first, last, Qt.rgba(0.3, 0.5, 0.7, 1),"volume", points, highestValume);
++            drawKLine(ctx, first, last, points, highestPrice);
++            ctx.restore();
++        }
++    }
++}
index 0000000,0000000..e368746
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,20 @@@
++TEMPLATE = lib
++CONFIG += qt plugin
++QT += qml network
++
++DESTDIR = com/nokia/StockChartExample
++TARGET  = qmlstockchartexampleplugin
++
++SOURCES += model.cpp  plugin.cpp
++HEADERS += model.h
++qdeclarativesources.files += \
++    com/nokia/StockChartExample/qmldir \
++    stock.qml
++
++qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/StockChartExample
++
++sources.files += stockchart.pro model.h model.cpp plugin.cpp README
++sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins
++target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/plugins/com/nokia/StockChartExample
++
++INSTALLS += qdeclarativesources sources target
index 0000000,0000000..4be0d26
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,721 @@@
++var tiger = [
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z"}
++  ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-118.774 81.262C-118.774 81.262 -119.323 83.078 -120.092 82.779C-120.86 82.481 -119.977 31.675 -140.043 26.801C-140.043 26.801 -120.82 25.937 -118.774 81.262z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-91.284 123.59C-91.284 123.59 -89.648 124.55 -90.118 125.227C-90.589 125.904 -139.763 113.102 -149.218 131.459C-149.218 131.459 -145.539 112.572 -91.284 123.59z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-94.093 133.801C-94.093 133.801 -92.237 134.197 -92.471 134.988C-92.704 135.779 -143.407 139.121 -146.597 159.522C-146.597 159.522 -149.055 140.437 -94.093 133.801z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-98.304 128.276C-98.304 128.276 -96.526 128.939 -96.872 129.687C-97.218 130.435 -147.866 126.346 -153.998 146.064C-153.998 146.064 -153.646 126.825 -98.304 128.276z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-109.009 110.072C-109.009 110.072 -107.701 111.446 -108.34 111.967C-108.979 112.488 -152.722 86.634 -166.869 101.676C-166.869 101.676 -158.128 84.533 -109.009 110.072z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-116.554 114.263C-116.554 114.263 -115.098 115.48 -115.674 116.071C-116.25 116.661 -162.638 95.922 -174.992 112.469C-174.992 112.469 -168.247 94.447 -116.554 114.263z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-119.154 118.335C-119.154 118.335 -117.546 119.343 -118.036 120.006C-118.526 120.669 -167.308 106.446 -177.291 124.522C-177.291 124.522 -173.066 105.749 -119.154 118.335z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-108.42 118.949C-108.42 118.949 -107.298 120.48 -107.999 120.915C-108.7 121.35 -148.769 90.102 -164.727 103.207C-164.727 103.207 -153.862 87.326 -108.42 118.949z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-128.2 90C-128.2 90 -127.6 91.8 -128.4 92C-129.2 92.2 -157.8 50.2 -177.001 57.8C-177.001 57.8 -161.8 46 -128.2 90z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-127.505 96.979C-127.505 96.979 -126.53 98.608 -127.269 98.975C-128.007 99.343 -164.992 64.499 -182.101 76.061C-182.101 76.061 -169.804 61.261 -127.505 96.979z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.172,
++  "path":"M-127.62 101.349C-127.62 101.349 -126.498 102.88 -127.199 103.315C-127.9 103.749 -167.969 72.502 -183.927 85.607C-183.927 85.607 -173.062 69.726 -127.62 101.349z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000",
++  "path":"M-129.83 103.065C-129.327 109.113 -128.339 115.682 -126.6 118.801C-126.6 118.801 -130.2 131.201 -121.4 144.401C-121.4 144.401 -121.8 151.601 -120.2 154.801C-120.2 154.801 -116.2 163.201 -111.4 164.001C-107.516 164.648 -98.793 167.717 -88.932 169.121C-88.932 169.121 -71.8 183.201 -75 196.001C-75 196.001 -75.4 212.401 -79 214.001C-79 214.001 -67.4 202.801 -77 219.601L-81.4 238.401C-81.4 238.401 -55.8 216.801 -71.4 235.201L-81.4 261.201C-81.4 261.201 -61.8 242.801 -69 251.201L-72.2 260.001C-72.2 260.001 -29 232.801 -59.8 262.401C-59.8 262.401 -51.8 258.801 -47.4 261.601C-47.4 261.601 -40.6 260.401 -41.4 262.001C-41.4 262.001 -62.2 272.401 -65.8 290.801C-65.8 290.801 -57.4 280.801 -60.6 291.601L-60.2 303.201C-60.2 303.201 -56.2 281.601 -56.6 319.201C-56.6 319.201 -37.4 301.201 -49 322.001L-49 338.801C-49 338.801 -33.8 322.401 -40.2 335.201C-40.2 335.201 -30.2 326.401 -34.2 341.601C-34.2 341.601 -35 352.001 -30.6 340.801C-30.6 340.801 -14.6 310.201 -20.6 336.401C-20.6 336.401 -21.4 355.601 -16.6 340.801C-16.6 340.801 -16.2 351.201 -7 358.401C-7 358.401 -8.2 307.601 4.6 343.601L8.6 360.001C8.6 360.001 11.4 350.801 11 345.601C11 345.601 25.8 329.201 19 353.601C19 353.601 34.2 330.801 31 344.001C31 344.001 23.4 360.001 25 364.801C25 364.801 41.8 330.001 43 328.401C43 328.401 41 370.802 51.8 334.801C51.8 334.801 57.4 346.801 54.6 351.201C54.6 351.201 62.6 343.201 61.8 340.001C61.8 340.001 66.4 331.801 69.2 345.401C69.2 345.401 71 354.801 72.6 351.601C72.6 351.601 76.6 375.602 77.8 352.801C77.8 352.801 79.4 339.201 72.2 327.601C72.2 327.601 73 324.401 70.2 320.401C70.2 320.401 83.8 342.001 76.6 313.201C76.6 313.201 87.801 321.201 89.001 321.201C89.001 321.201 75.4 298.001 84.2 302.801C84.2 302.801 79 292.401 97.001 304.401C97.001 304.401 81 288.401 98.601 298.001C98.601 298.001 106.601 304.401 99.001 294.401C99.001 294.401 84.6 278.401 106.601 296.401C106.601 296.401 118.201 312.801 119.001 315.601C119.001 315.601 109.001 286.401 104.601 283.601C104.601 283.601 113.001 247.201 154.201 262.801C154.201 262.801 161.001 280.001 165.401 261.601C165.401 261.601 178.201 255.201 189.401 282.801C189.401 282.801 193.401 269.201 192.601 266.401C192.601 266.401 199.401 267.601 198.601 266.401C198.601 266.401 211.801 270.801 213.001 270.001C213.001 270.001 219.801 276.801 220.201 273.201C220.201 273.201 229.401 276.001 227.401 272.401C227.401 272.401 236.201 288.001 236.601 291.601L239.001 277.601L241.001 280.401C241.001 280.401 242.601 272.801 241.801 271.601C241.001 270.401 261.801 278.401 266.601 299.201L268.601 307.601C268.601 307.601 274.601 292.801 273.001 288.801C273.001 288.801 278.201 289.601 278.601 294.001C278.601 294.001 282.601 270.801 277.801 264.801C277.801 264.801 282.201 264.001 283.401 267.601L283.401 260.401C283.401 260.401 290.601 261.201 290.601 258.801C290.601 258.801 295.001 254.801 297.001 259.601C297.001 259.601 284.601 224.401 303.001 243.601C303.001 243.601 310.201 254.401 306.601 235.601C303.001 216.801 299.001 215.201 303.801 214.801C303.801 214.801 304.601 211.201 302.601 209.601C300.601 208.001 303.801 209.601 303.801 209.601C303.801 209.601 308.601 213.601 303.401 191.601C303.401 191.601 309.801 193.201 297.801 164.001C297.801 164.001 300.601 161.601 296.601 153.201C296.601 153.201 304.601 157.601 307.401 156.001C307.401 156.001 307.001 154.401 303.801 150.401C303.801 150.401 282.201 95.6 302.601 117.601C302.601 117.601 314.451 131.151 308.051 108.351C308.051 108.351 298.94 84.341 299.717 80.045L-129.83 103.065z"}
++ ,
++ {"fill": "#cc7226", "stroke":"#000000",
++  "path":"M299.717 80.245C300.345 80.426 302.551 81.55 303.801 83.2C303.801 83.2 310.601 94 305.401 75.6C305.401 75.6 296.201 46.8 305.001 58C305.001 58 311.001 65.2 307.801 51.6C303.936 35.173 301.401 28.8 301.401 28.8C301.401 28.8 313.001 33.6 286.201 -6L295.001 -2.4C295.001 -2.4 275.401 -42 253.801 -47.2L245.801 -53.2C245.801 -53.2 284.201 -91.2 271.401 -128C271.401 -128 264.601 -133.2 255.001 -124C255.001 -124 248.601 -119.2 242.601 -120.8C242.601 -120.8 211.801 -119.6 209.801 -119.6C207.801 -119.6 173.001 -156.8 107.401 -139.2C107.401 -139.2 102.201 -137.2 97.801 -138.4C97.801 -138.4 79.4 -154.4 30.6 -131.6C30.6 -131.6 20.6 -129.6 19 -129.6C17.4 -129.6 14.6 -129.6 6.6 -123.2C-1.4 -116.8 -1.8 -116 -3.8 -114.4C-3.8 -114.4 -20.2 -103.2 -25 -102.4C-25 -102.4 -36.6 -96 -41 -86L-44.6 -84.8C-44.6 -84.8 -46.2 -77.6 -46.6 -76.4C-46.6 -76.4 -51.4 -72.8 -52.2 -67.2C-52.2 -67.2 -61 -61.2 -60.6 -56.8C-60.6 -56.8 -62.2 -51.6 -63 -46.8C-63 -46.8 -70.2 -42 -69.4 -39.2C-69.4 -39.2 -77 -25.2 -75.8 -18.4C-75.8 -18.4 -82.2 -18.8 -85 -16.4C-85 -16.4 -85.8 -11.6 -87.4 -11.2C-87.4 -11.2 -90.2 -10 -87.8 -6C-87.8 -6 -89.4 -3.2 -89.8 -1.6C-89.8 -1.6 -89 1.2 -93.4 6.8C-93.4 6.8 -99.8 25.6 -97.8 30.8C-97.8 30.8 -97.4 35.6 -100.2 37.2C-100.2 37.2 -103.8 36.8 -95.4 48.8C-95.4 48.8 -94.6 50 -97.8 52.4C-97.8 52.4 -115 56 -117.4 72.4C-117.4 72.4 -131 87.2 -131 92.4C-131 94.705 -130.729 97.852 -130.03 102.465C-130.03 102.465 -130.6 110.801 -103 111.601C-75.4 112.401 299.717 80.245 299.717 80.245z"}
++ ,
++ {"fill": "#cc7226",
++  "path":"M-115.6 102.6C-140.6 63.2 -126.2 119.601 -126.2 119.601C-117.4 154.001 12.2 116.401 12.2 116.401C12.2 116.401 181.001 86 192.201 82C203.401 78 298.601 84.4 298.601 84.4L293.001 67.6C228.201 21.2 209.001 44.4 195.401 40.4C181.801 36.4 184.201 46 181.001 46.8C177.801 47.6 138.601 22.8 132.201 23.6C125.801 24.4 100.459 0.649 115.401 32.4C131.401 66.4 57 71.6 40.2 60.4C23.4 49.2 47.4 78.8 47.4 78.8C65.8 98.8 31.4 82 31.4 82C-3 69.2 -27 94.8 -30.2 95.6C-33.4 96.4 -38.2 99.6 -39 93.2C-39.8 86.8 -47.31 70.099 -79 96.4C-99 113.001 -112.8 91 -112.8 91L-115.6 102.6z"}
++ ,
++ {"fill": "#e87f3a",
++  "path":"M133.51 25.346C127.11 26.146 101.743 2.407 116.71 34.146C133.31 69.346 58.31 73.346 41.51 62.146C24.709 50.946 48.71 80.546 48.71 80.546C67.11 100.546 32.709 83.746 32.709 83.746C-1.691 70.946 -25.691 96.546 -28.891 97.346C-32.091 98.146 -36.891 101.346 -37.691 94.946C-38.491 88.546 -45.87 72.012 -77.691 98.146C-98.927 115.492 -112.418 94.037 -112.418 94.037L-115.618 104.146C-140.618 64.346 -125.546 122.655 -125.546 122.655C-116.745 157.056 13.509 118.146 13.509 118.146C13.509 118.146 182.31 87.746 193.51 83.746C204.71 79.746 299.038 86.073 299.038 86.073L293.51 68.764C228.71 22.364 210.31 46.146 196.71 42.146C183.11 38.146 185.51 47.746 182.31 48.546C179.11 49.346 139.91 24.546 133.51 25.346z"}
++ ,
++ {"fill": "#ea8c4d",
++  "path":"M134.819 27.091C128.419 27.891 103.685 3.862 118.019 35.891C134.219 72.092 59.619 75.092 42.819 63.892C26.019 52.692 50.019 82.292 50.019 82.292C68.419 102.292 34.019 85.492 34.019 85.492C-0.381 72.692 -24.382 98.292 -27.582 99.092C-30.782 99.892 -35.582 103.092 -36.382 96.692C-37.182 90.292 -44.43 73.925 -76.382 99.892C-98.855 117.983 -112.036 97.074 -112.036 97.074L-115.636 105.692C-139.436 66.692 -124.891 125.71 -124.891 125.71C-116.091 160.11 14.819 119.892 14.819 119.892C14.819 119.892 183.619 89.492 194.819 85.492C206.019 81.492 299.474 87.746 299.474 87.746L294.02 69.928C229.219 23.528 211.619 47.891 198.019 43.891C184.419 39.891 186.819 49.491 183.619 50.292C180.419 51.092 141.219 26.291 134.819 27.091z"}
++ ,
++ {"fill": "#ec9961",
++  "path":"M136.128 28.837C129.728 29.637 104.999 5.605 119.328 37.637C136.128 75.193 60.394 76.482 44.128 65.637C27.328 54.437 51.328 84.037 51.328 84.037C69.728 104.037 35.328 87.237 35.328 87.237C0.928 74.437 -23.072 100.037 -26.272 100.837C-29.472 101.637 -34.272 104.837 -35.072 98.437C-35.872 92.037 -42.989 75.839 -75.073 101.637C-98.782 120.474 -111.655 100.11 -111.655 100.11L-115.655 107.237C-137.455 70.437 -124.236 128.765 -124.236 128.765C-115.436 163.165 16.128 121.637 16.128 121.637C16.128 121.637 184.928 91.237 196.129 87.237C207.329 83.237 299.911 89.419 299.911 89.419L294.529 71.092C229.729 24.691 212.929 49.637 199.329 45.637C185.728 41.637 188.128 51.237 184.928 52.037C181.728 52.837 142.528 28.037 136.128 28.837z"}
++ ,
++ {"fill": "#eea575",
++  "path":"M137.438 30.583C131.037 31.383 106.814 7.129 120.637 39.383C137.438 78.583 62.237 78.583 45.437 67.383C28.637 56.183 52.637 85.783 52.637 85.783C71.037 105.783 36.637 88.983 36.637 88.983C2.237 76.183 -21.763 101.783 -24.963 102.583C-28.163 103.383 -32.963 106.583 -33.763 100.183C-34.563 93.783 -41.548 77.752 -73.763 103.383C-98.709 122.965 -111.273 103.146 -111.273 103.146L-115.673 108.783C-135.473 73.982 -123.582 131.819 -123.582 131.819C-114.782 166.22 17.437 123.383 17.437 123.383C17.437 123.383 186.238 92.983 197.438 88.983C208.638 84.983 300.347 91.092 300.347 91.092L295.038 72.255C230.238 25.855 214.238 51.383 200.638 47.383C187.038 43.383 189.438 52.983 186.238 53.783C183.038 54.583 143.838 29.783 137.438 30.583z"}
++ ,
++ {"fill": "#f1b288",
++  "path":"M138.747 32.328C132.347 33.128 106.383 9.677 121.947 41.128C141.147 79.928 63.546 80.328 46.746 69.128C29.946 57.928 53.946 87.528 53.946 87.528C72.346 107.528 37.946 90.728 37.946 90.728C3.546 77.928 -20.454 103.528 -23.654 104.328C-26.854 105.128 -31.654 108.328 -32.454 101.928C-33.254 95.528 -40.108 79.665 -72.454 105.128C-98.636 125.456 -110.891 106.183 -110.891 106.183L-115.691 110.328C-133.691 77.128 -122.927 134.874 -122.927 134.874C-114.127 169.274 18.746 125.128 18.746 125.128C18.746 125.128 187.547 94.728 198.747 90.728C209.947 86.728 300.783 92.764 300.783 92.764L295.547 73.419C230.747 27.019 215.547 53.128 201.947 49.128C188.347 45.128 190.747 54.728 187.547 55.528C184.347 56.328 145.147 31.528 138.747 32.328z"}
++ ,
++ {"fill": "#f3bf9c",
++  "path":"M140.056 34.073C133.655 34.873 107.313 11.613 123.255 42.873C143.656 82.874 64.855 82.074 48.055 70.874C31.255 59.674 55.255 89.274 55.255 89.274C73.655 109.274 39.255 92.474 39.255 92.474C4.855 79.674 -19.145 105.274 -22.345 106.074C-25.545 106.874 -30.345 110.074 -31.145 103.674C-31.945 97.274 -38.668 81.578 -71.145 106.874C-98.564 127.947 -110.509 109.219 -110.509 109.219L-115.709 111.874C-131.709 81.674 -122.273 137.929 -122.273 137.929C-113.473 172.329 20.055 126.874 20.055 126.874C20.055 126.874 188.856 96.474 200.056 92.474C211.256 88.474 301.22 94.437 301.22 94.437L296.056 74.583C231.256 28.183 216.856 54.874 203.256 50.874C189.656 46.873 192.056 56.474 188.856 57.274C185.656 58.074 146.456 33.273 140.056 34.073z"}
++ ,
++ {"fill": "#f5ccb0",
++  "path":"M141.365 35.819C134.965 36.619 107.523 13.944 124.565 44.619C146.565 84.219 66.164 83.819 49.364 72.619C32.564 61.419 56.564 91.019 56.564 91.019C74.964 111.019 40.564 94.219 40.564 94.219C6.164 81.419 -17.836 107.019 -21.036 107.819C-24.236 108.619 -29.036 111.819 -29.836 105.419C-30.636 99.019 -37.227 83.492 -69.836 108.619C-98.491 130.438 -110.127 112.256 -110.127 112.256L-115.727 113.419C-130.128 85.019 -121.618 140.983 -121.618 140.983C-112.818 175.384 21.364 128.619 21.364 128.619C21.364 128.619 190.165 98.219 201.365 94.219C212.565 90.219 301.656 96.11 301.656 96.11L296.565 75.746C231.765 29.346 218.165 56.619 204.565 52.619C190.965 48.619 193.365 58.219 190.165 59.019C186.965 59.819 147.765 35.019 141.365 35.819z"}
++ ,
++ {"fill": "#f8d8c4",
++  "path":"M142.674 37.565C136.274 38.365 108.832 15.689 125.874 46.365C147.874 85.965 67.474 85.565 50.674 74.365C33.874 63.165 57.874 92.765 57.874 92.765C76.274 112.765 41.874 95.965 41.874 95.965C7.473 83.165 -16.527 108.765 -19.727 109.565C-22.927 110.365 -27.727 113.565 -28.527 107.165C-29.327 100.765 -35.786 85.405 -68.527 110.365C-98.418 132.929 -109.745 115.293 -109.745 115.293L-115.745 114.965C-129.346 88.564 -120.963 144.038 -120.963 144.038C-112.163 178.438 22.673 130.365 22.673 130.365C22.673 130.365 191.474 99.965 202.674 95.965C213.874 91.965 302.093 97.783 302.093 97.783L297.075 76.91C232.274 30.51 219.474 58.365 205.874 54.365C192.274 50.365 194.674 59.965 191.474 60.765C188.274 61.565 149.074 36.765 142.674 37.565z"}
++ ,
++ {"fill": "#fae5d7",
++  "path":"M143.983 39.31C137.583 40.11 110.529 17.223 127.183 48.11C149.183 88.91 68.783 87.31 51.983 76.11C35.183 64.91 59.183 94.51 59.183 94.51C77.583 114.51 43.183 97.71 43.183 97.71C8.783 84.91 -15.217 110.51 -18.417 111.31C-21.618 112.11 -26.418 115.31 -27.218 108.91C-28.018 102.51 -34.346 87.318 -67.218 112.11C-98.345 135.42 -109.363 118.329 -109.363 118.329L-115.764 116.51C-128.764 92.51 -120.309 147.093 -120.309 147.093C-111.509 181.493 23.983 132.11 23.983 132.11C23.983 132.11 192.783 101.71 203.983 97.71C215.183 93.71 302.529 99.456 302.529 99.456L297.583 78.074C232.783 31.673 220.783 60.11 207.183 56.11C193.583 52.11 195.983 61.71 192.783 62.51C189.583 63.31 150.383 38.51 143.983 39.31z"}
++ ,
++ {"fill": "#fcf2eb",
++  "path":"M145.292 41.055C138.892 41.855 112.917 18.411 128.492 49.855C149.692 92.656 70.092 89.056 53.292 77.856C36.492 66.656 60.492 96.256 60.492 96.256C78.892 116.256 44.492 99.456 44.492 99.456C10.092 86.656 -13.908 112.256 -17.108 113.056C-20.308 113.856 -25.108 117.056 -25.908 110.656C-26.708 104.256 -32.905 89.232 -65.908 113.856C-98.273 137.911 -108.982 121.365 -108.982 121.365L-115.782 118.056C-128.582 94.856 -119.654 150.147 -119.654 150.147C-110.854 184.547 25.292 133.856 25.292 133.856C25.292 133.856 194.093 103.456 205.293 99.456C216.493 95.456 302.965 101.128 302.965 101.128L298.093 79.237C233.292 32.837 222.093 61.856 208.493 57.856C194.893 53.855 197.293 63.456 194.093 64.256C190.892 65.056 151.692 40.255 145.292 41.055z"}
++ ,
++ {"fill": "#ffffff",
++  "path":"M-115.8 119.601C-128.6 97.6 -119 153.201 -119 153.201C-110.2 187.601 26.6 135.601 26.6 135.601C26.6 135.601 195.401 105.2 206.601 101.2C217.801 97.2 303.401 102.8 303.401 102.8L298.601 80.4C233.801 34 223.401 63.6 209.801 59.6C196.201 55.6 198.601 65.2 195.401 66C192.201 66.8 153.001 42 146.601 42.8C140.201 43.6 114.981 19.793 129.801 51.6C152.028 99.307 69.041 89.227 54.6 79.6C37.8 68.4 61.8 98 61.8 98C80.2 118.001 45.8 101.2 45.8 101.2C11.4 88.4 -12.6 114.001 -15.8 114.801C-19 115.601 -23.8 118.801 -24.6 112.401C-25.4 106 -31.465 91.144 -64.6 115.601C-98.2 140.401 -108.6 124.401 -108.6 124.401L-115.8 119.601z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-74.2 149.601C-74.2 149.601 -81.4 161.201 -60.6 174.401C-60.6 174.401 -59.2 175.801 -77.2 171.601C-77.2 171.601 -83.4 169.601 -85 159.201C-85 159.201 -89.8 154.801 -94.6 149.201C-99.4 143.601 -74.2 149.601 -74.2 149.601z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M65.8 102C65.8 102 83.498 128.821 82.9 133.601C81.6 144.001 81.4 153.601 84.6 157.601C87.801 161.601 96.601 194.801 96.601 194.801C96.601 194.801 96.201 196.001 108.601 158.001C108.601 158.001 120.201 142.001 100.201 123.601C100.201 123.601 65 94.8 65.8 102z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-54.2 176.401C-54.2 176.401 -43 183.601 -57.4 214.801L-51 212.401C-51 212.401 -51.8 223.601 -55 226.001L-47.8 222.801C-47.8 222.801 -43 230.801 -47 235.601C-47 235.601 -30.2 243.601 -31 250.001C-31 250.001 -24.6 242.001 -28.6 235.601C-32.6 229.201 -39.8 233.201 -39 214.801L-47.8 218.001C-47.8 218.001 -42.2 209.201 -42.2 202.801L-50.2 205.201C-50.2 205.201 -34.731 178.623 -45.4 177.201C-51.4 176.401 -54.2 176.401 -54.2 176.401z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-21.8 193.201C-21.8 193.201 -19 188.801 -21.8 189.601C-24.6 190.401 -55.8 205.201 -61.8 214.801C-61.8 214.801 -27.4 190.401 -21.8 193.201z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-11.4 201.201C-11.4 201.201 -8.6 196.801 -11.4 197.601C-14.2 198.401 -45.4 213.201 -51.4 222.801C-51.4 222.801 -17 198.401 -11.4 201.201z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M1.8 186.001C1.8 186.001 4.6 181.601 1.8 182.401C-1 183.201 -32.2 198.001 -38.2 207.601C-38.2 207.601 -3.8 183.201 1.8 186.001z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-21.4 229.601C-21.4 229.601 -21.4 223.601 -24.2 224.401C-27 225.201 -63 242.801 -69 252.401C-69 252.401 -27 226.801 -21.4 229.601z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-20.2 218.801C-20.2 218.801 -19 214.001 -21.8 214.801C-23.8 214.801 -50.2 226.401 -56.2 236.001C-56.2 236.001 -26.6 214.401 -20.2 218.801z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-34.6 266.401L-44.6 274.001C-44.6 274.001 -34.2 266.401 -30.6 267.601C-30.6 267.601 -37.4 278.801 -38.2 284.001C-38.2 284.001 -27.8 271.201 -22.2 271.601C-22.2 271.601 -14.6 272.001 -14.6 282.801C-14.6 282.801 -9 272.401 -5.8 272.801C-5.8 272.801 -4.6 279.201 -5.8 286.001C-5.8 286.001 -1.8 278.401 2.2 280.001C2.2 280.001 8.6 278.001 7.8 289.601C7.8 289.601 7.8 300.001 7 302.801C7 302.801 12.6 276.401 15 276.001C15 276.001 23 274.801 27.8 283.601C27.8 283.601 23.8 276.001 28.6 278.001C28.6 278.001 39.4 279.601 42.6 286.401C42.6 286.401 35.8 274.401 41.4 277.601C41.4 277.601 48.2 277.601 49.4 284.001C49.4 284.001 57.8 305.201 59.8 306.801C59.8 306.801 52.2 285.201 53.8 285.201C53.8 285.201 51.8 273.201 57 288.001C57 288.001 53.8 274.001 59.4 274.801C65 275.601 69.4 285.601 77.8 283.201C77.8 283.201 87.401 288.801 89.401 219.601L-34.6 266.401z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-29.8 173.601C-29.8 173.601 -15 167.601 25 173.601C25 173.601 32.2 174.001 39 165.201C45.8 156.401 72.6 149.201 79 151.201L88.601 157.601L89.401 158.801C89.401 158.801 101.801 169.201 102.201 176.801C102.601 184.401 87.801 232.401 78.2 248.401C68.6 264.401 59 276.801 39.8 274.401C39.8 274.401 19 270.401 -6.6 274.401C-6.6 274.401 -35.8 272.801 -38.6 264.801C-41.4 256.801 -27.4 241.601 -27.4 241.601C-27.4 241.601 -23 233.201 -24.2 218.801C-25.4 204.401 -25 176.401 -29.8 173.601z"}
++ ,
++ {"fill": "#e5668c",
++  "path":"M-7.8 175.601C0.6 194.001 -29 259.201 -29 259.201C-31 260.801 -16.34 266.846 -6.2 264.401C4.746 261.763 45 266.001 45 266.001C68.6 250.401 81.4 206.001 81.4 206.001C81.4 206.001 91.801 182.001 74.2 178.801C56.6 175.601 -7.8 175.601 -7.8 175.601z"}
++ ,
++ {"fill": "#b23259",
++  "path":"M-9.831 206.497C-6.505 193.707 -4.921 181.906 -7.8 175.601C-7.8 175.601 54.6 182.001 65.8 161.201C70.041 153.326 84.801 184.001 84.4 193.601C84.4 193.601 21.4 208.001 6.6 196.801L-9.831 206.497z"}
++ ,
++ {"fill": "#a5264c",
++  "path":"M-5.4 222.801C-5.4 222.801 -3.4 230.001 -5.8 234.001C-5.8 234.001 -7.4 234.801 -8.6 235.201C-8.6 235.201 -7.4 238.801 -1.4 240.401C-1.4 240.401 0.6 244.801 3 245.201C5.4 245.601 10.2 251.201 14.2 250.001C18.2 248.801 29.4 244.801 29.4 244.801C29.4 244.801 35 241.601 43.8 245.201C43.8 245.201 46.175 244.399 46.6 240.401C47.1 235.701 50.2 232.001 52.2 230.001C54.2 228.001 63.8 215.201 62.6 214.801C61.4 214.401 -5.4 222.801 -5.4 222.801z"}
++ ,
++ {"fill": "#ff727f", "stroke":"#000000",
++  "path":"M-9.8 174.401C-9.8 174.401 -12.6 196.801 -9.4 205.201C-6.2 213.601 -7 215.601 -7.8 219.601C-8.6 223.601 -4.2 233.601 1.4 239.601L13.4 241.201C13.4 241.201 28.6 237.601 37.8 240.401C37.8 240.401 46.794 241.744 50.2 226.801C50.2 226.801 55 220.401 62.2 217.601C69.4 214.801 76.6 173.201 72.6 165.201C68.6 157.201 54.2 152.801 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-8.2 249.201C-8.2 249.201 -9 247.201 -13.4 246.801C-13.4 246.801 -35.8 243.201 -44.2 230.801C-44.2 230.801 -51 225.201 -46.6 236.801C-46.6 236.801 -36.2 257.201 -29.4 260.001C-29.4 260.001 -13 264.001 -8.2 249.201z"}
++ ,
++ {"fill": "#cc3f4c",
++  "path":"M71.742 185.229C72.401 177.323 74.354 168.709 72.6 165.201C66.154 152.307 49.181 157.695 38.2 168.401C22.2 184.001 20.2 167.201 -9.8 174.401C-9.8 174.401 -11.545 188.364 -10.705 198.376C-10.705 198.376 26.6 186.801 27.4 192.401C27.4 192.401 29 189.201 38.2 189.201C47.4 189.201 70.142 188.029 71.742 185.229z"}
++ ,
++ {"stroke":"#a51926", "width":2,
++  "path":"M28.6 175.201C28.6 175.201 33.4 180.001 29.8 189.601C29.8 189.601 15.4 205.601 17.4 219.601"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-19.4 260.001C-19.4 260.001 -23.8 247.201 -15 254.001C-15 254.001 -10.2 256.001 -11.4 257.601C-12.6 259.201 -18.2 263.201 -19.4 260.001z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-14.36 261.201C-14.36 261.201 -17.88 250.961 -10.84 256.401C-10.84 256.401 -6.419 258.849 -7.96 259.281C-12.52 260.561 -7.96 263.121 -14.36 261.201z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-9.56 261.201C-9.56 261.201 -13.08 250.961 -6.04 256.401C-6.04 256.401 -1.665 258.711 -3.16 259.281C-6.52 260.561 -3.16 263.121 -9.56 261.201z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-2.96 261.401C-2.96 261.401 -6.48 251.161 0.56 256.601C0.56 256.601 4.943 258.933 3.441 259.481C0.48 260.561 3.441 263.321 -2.96 261.401z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M3.52 261.321C3.52 261.321 0 251.081 7.041 256.521C7.041 256.521 10.881 258.121 9.921 259.401C8.961 260.681 9.921 263.241 3.52 261.321z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M10.2 262.001C10.2 262.001 5.4 249.601 14.6 256.001C14.6 256.001 19.4 258.001 18.2 259.601C17 261.201 18.2 264.401 10.2 262.001z"}
++ ,
++ {"stroke":"#a5264c", "width":2,
++  "path":"M-18.2 244.801C-18.2 244.801 -5 242.001 1 245.201C1 245.201 7 246.401 8.2 246.001C9.4 245.601 12.6 245.201 12.6 245.201"}
++ ,
++ {"stroke":"#a5264c", "width":2,
++  "path":"M15.8 253.601C15.8 253.601 27.8 240.001 39.8 244.401C46.816 246.974 45.8 243.601 46.6 240.801C47.4 238.001 47.6 233.801 52.6 230.801"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M33 237.601C33 237.601 29 226.801 26.2 239.601C23.4 252.401 20.2 256.001 18.6 258.801C18.6 258.801 18.6 264.001 27 263.601C27 263.601 37.8 263.201 38.2 260.401C38.6 257.601 37 246.001 33 237.601z"}
++ ,
++ {"stroke":"#a5264c", "width":2,
++  "path":"M47 244.801C47 244.801 50.6 242.401 53 243.601"}
++ ,
++ {"stroke":"#a5264c", "width":2,
++  "path":"M53.5 228.401C53.5 228.401 56.4 223.501 61.2 222.701"}
++ ,
++ {"fill": "#b2b2b2",
++  "path":"M-25.8 265.201C-25.8 265.201 -7.8 268.401 -3.4 266.801C-3.4 266.801 5.4 266.801 -3 268.801C-3 268.801 -15.8 268.801 -23.8 267.601C-23.8 267.601 -35.4 262.001 -25.8 265.201z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-11.8 172.001C-11.8 172.001 5.8 172.001 7.8 172.801C7.8 172.801 15 203.601 11.4 211.201C11.4 211.201 10.2 214.001 7.4 208.401C7.4 208.401 -11 175.601 -14.2 173.601C-17.4 171.601 -13 172.001 -11.8 172.001z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-88.9 169.301C-88.9 169.301 -80 171.001 -67.4 173.601C-67.4 173.601 -62.6 196.001 -59.4 200.801C-56.2 205.601 -59.8 205.601 -63.4 202.801C-67 200.001 -81.8 186.001 -83.8 181.601C-85.8 177.201 -88.9 169.301 -88.9 169.301z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-67.039 173.818C-67.039 173.818 -61.239 175.366 -60.23 177.581C-59.222 179.795 -61.432 183.092 -61.432 183.092C-61.432 183.092 -62.432 186.397 -63.634 184.235C-64.836 182.072 -67.708 174.412 -67.039 173.818z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-67 173.601C-67 173.601 -63.4 178.801 -59.8 178.801C-56.2 178.801 -55.818 178.388 -53 179.001C-48.4 180.001 -48.8 178.001 -42.2 179.201C-39.56 179.681 -37 178.801 -34.2 180.001C-31.4 181.201 -28.2 180.401 -27 178.401C-25.8 176.401 -21 172.201 -21 172.201C-21 172.201 -33.8 174.001 -36.6 174.801C-36.6 174.801 -59 176.001 -67 173.601z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-22.4 173.801C-22.4 173.801 -28.85 177.301 -29.25 179.701C-29.65 182.101 -24 185.801 -24 185.801C-24 185.801 -21.25 190.401 -20.65 188.001C-20.05 185.601 -21.6 174.201 -22.4 173.801z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-59.885 179.265C-59.885 179.265 -52.878 190.453 -52.661 179.242C-52.661 179.242 -52.104 177.984 -53.864 177.962C-59.939 177.886 -58.418 173.784 -59.885 179.265z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-52.707 179.514C-52.707 179.514 -44.786 190.701 -45.422 179.421C-45.422 179.421 -45.415 179.089 -47.168 178.936C-51.915 178.522 -51.57 174.004 -52.707 179.514z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-45.494 179.522C-45.494 179.522 -37.534 190.15 -38.203 180.484C-38.203 180.484 -38.084 179.251 -39.738 178.95C-43.63 178.244 -43.841 174.995 -45.494 179.522z"}
++ ,
++ {"fill": "#ffffcc", "stroke":"#000000", "width":0.5,
++  "path":"M-38.618 179.602C-38.618 179.602 -30.718 191.163 -30.37 181.382C-30.37 181.382 -28.726 180.004 -30.472 179.782C-36.29 179.042 -35.492 174.588 -38.618 179.602z"}
++ ,
++ {"fill": "#e5e5b2",
++  "path":"M-74.792 183.132L-82.45 181.601C-85.05 176.601 -87.15 170.451 -87.15 170.451C-87.15 170.451 -80.8 171.451 -68.3 174.251C-68.3 174.251 -67.424 177.569 -65.952 183.364L-74.792 183.132z"}
++ ,
++ {"fill": "#e5e5b2",
++  "path":"M-9.724 178.47C-11.39 175.964 -12.707 174.206 -13.357 173.8C-16.37 171.917 -12.227 172.294 -11.098 172.294C-11.098 172.294 5.473 172.294 7.356 173.047C7.356 173.047 7.88 175.289 8.564 178.68C8.564 178.68 -1.524 176.67 -9.724 178.47z"}
++ ,
++ {"fill": "#cc7226",
++  "path":"M43.88 40.321C71.601 44.281 97.121 8.641 98.881 -1.04C100.641 -10.72 90.521 -22.6 90.521 -22.6C91.841 -25.68 87.001 -39.76 81.721 -49C76.441 -58.24 60.54 -57.266 43 -58.24C27.16 -59.12 8.68 -35.8 7.36 -34.04C6.04 -32.28 12.2 6.001 13.52 11.721C14.84 17.441 12.2 43.841 12.2 43.841C46.44 34.741 16.16 36.361 43.88 40.321z"}
++ ,
++ {"fill": "#ea8e51",
++  "path":"M8.088 -33.392C6.792 -31.664 12.84 5.921 14.136 11.537C15.432 17.153 12.84 43.073 12.84 43.073C45.512 34.193 16.728 35.729 43.944 39.617C71.161 43.505 96.217 8.513 97.945 -0.992C99.673 -10.496 89.737 -22.16 89.737 -22.16C91.033 -25.184 86.281 -39.008 81.097 -48.08C75.913 -57.152 60.302 -56.195 43.08 -57.152C27.528 -58.016 9.384 -35.12 8.088 -33.392z"}
++ ,
++ {"fill": "#efaa7c",
++  "path":"M8.816 -32.744C7.544 -31.048 13.48 5.841 14.752 11.353C16.024 16.865 13.48 42.305 13.48 42.305C44.884 33.145 17.296 35.097 44.008 38.913C70.721 42.729 95.313 8.385 97.009 -0.944C98.705 -10.272 88.953 -21.72 88.953 -21.72C90.225 -24.688 85.561 -38.256 80.473 -47.16C75.385 -56.064 60.063 -55.125 43.16 -56.064C27.896 -56.912 10.088 -34.44 8.816 -32.744z"}
++ ,
++ {"fill": "#f4c6a8",
++  "path":"M9.544 -32.096C8.296 -30.432 14.12 5.761 15.368 11.169C16.616 16.577 14.12 41.537 14.12 41.537C43.556 32.497 17.864 34.465 44.072 38.209C70.281 41.953 94.409 8.257 96.073 -0.895C97.737 -10.048 88.169 -21.28 88.169 -21.28C89.417 -24.192 84.841 -37.504 79.849 -46.24C74.857 -54.976 59.824 -54.055 43.24 -54.976C28.264 -55.808 10.792 -33.76 9.544 -32.096z"}
++ ,
++ {"fill": "#f9e2d3",
++  "path":"M10.272 -31.448C9.048 -29.816 14.76 5.681 15.984 10.985C17.208 16.289 14.76 40.769 14.76 40.769C42.628 31.849 18.432 33.833 44.136 37.505C69.841 41.177 93.505 8.129 95.137 -0.848C96.769 -9.824 87.385 -20.84 87.385 -20.84C88.609 -23.696 84.121 -36.752 79.225 -45.32C74.329 -53.888 59.585 -52.985 43.32 -53.888C28.632 -54.704 11.496 -33.08 10.272 -31.448z"}
++ ,
++ {"fill": "#ffffff",
++  "path":"M44.2 36.8C69.4 40.4 92.601 8 94.201 -0.8C95.801 -9.6 86.601 -20.4 86.601 -20.4C87.801 -23.2 83.4 -36 78.6 -44.4C73.8 -52.8 59.346 -51.914 43.4 -52.8C29 -53.6 12.2 -32.4 11 -30.8C9.8 -29.2 15.4 5.6 16.6 10.8C17.8 16 15.4 40 15.4 40C40.9 31.4 19 33.2 44.2 36.8z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M90.601 2.8C90.601 2.8 62.8 10.4 51.2 8.8C51.2 8.8 35.4 2.2 26.6 24C26.6 24 23 31.2 21 33.2C19 35.2 90.601 2.8 90.601 2.8z"}
++ ,
++ {"fill": "#000000",
++  "path":"M94.401 0.6C94.401 0.6 65.4 12.8 55.4 12.4C55.4 12.4 39 7.8 30.6 22.4C30.6 22.4 22.2 31.6 19 33.2C19 33.2 18.6 34.8 25 30.8L35.4 36C35.4 36 50.2 45.6 59.8 29.6C59.8 29.6 63.8 18.4 63.8 16.4C63.8 14.4 85 8.8 86.601 8.4C88.201 8 94.801 3.8 94.401 0.6z"}
++ ,
++ {"fill": "#99cc32",
++  "path":"M47 36.514C40.128 36.514 31.755 32.649 31.755 26.4C31.755 20.152 40.128 13.887 47 13.887C53.874 13.887 59.446 18.952 59.446 25.2C59.446 31.449 53.874 36.514 47 36.514z"}
++ ,
++ {"fill": "#659900",
++  "path":"M43.377 19.83C38.531 20.552 33.442 22.055 33.514 21.839C35.054 17.22 41.415 13.887 47 13.887C51.296 13.887 55.084 15.865 57.32 18.875C57.32 18.875 52.004 18.545 43.377 19.83z"}
++ ,
++ {"fill": "#ffffff",
++  "path":"M55.4 19.6C55.4 19.6 51 16.4 51 18.6C51 18.6 54.6 23 55.4 19.6z"}
++ ,
++ {"fill": "#000000",
++  "path":"M45.4 27.726C42.901 27.726 40.875 25.7 40.875 23.2C40.875 20.701 42.901 18.675 45.4 18.675C47.9 18.675 49.926 20.701 49.926 23.2C49.926 25.7 47.9 27.726 45.4 27.726z"}
++ ,
++ {"fill": "#cc7226",
++  "path":"M-58.6 14.4C-58.6 14.4 -61.8 -6.8 -59.4 -11.2C-59.4 -11.2 -48.6 -21.2 -49 -24.8C-49 -24.8 -49.4 -42.8 -50.6 -43.6C-51.8 -44.4 -59.4 -50.4 -65.4 -44C-65.4 -44 -75.8 -26 -75 -19.6L-75 -17.6C-75 -17.6 -82.6 -18 -84.2 -16C-84.2 -16 -85.4 -10.8 -86.6 -10.4C-86.6 -10.4 -89.4 -8 -87.4 -5.2C-87.4 -5.2 -89.4 -2.8 -89 1.2L-81.4 5.2C-81.4 5.2 -79.4 19.6 -68.6 24.8C-63.764 27.129 -60.6 20.4 -58.6 14.4z"}
++ ,
++ {"fill": "#ffffff",
++  "path":"M-59.6 12.56C-59.6 12.56 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.48 -40.36 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.96 -59.6 12.56z"}
++ ,
++ {"fill": "#eb955c",
++  "path":"M-51.05 -42.61C-52.14 -43.47 -59.63 -49.24 -65.48 -43C-65.48 -43 -75.62 -25.45 -74.84 -19.21L-74.84 -17.26C-74.84 -17.26 -82.25 -17.65 -83.81 -15.7C-83.81 -15.7 -84.98 -10.63 -86.15 -10.24C-86.15 -10.24 -88.88 -7.9 -86.93 -5.17C-86.93 -5.17 -88.88 -2.83 -88.49 1.07L-81.08 4.97C-81.08 4.97 -79.13 19.01 -68.6 24.08C-63.886 26.35 -60.8 19.79 -58.85 13.94C-58.85 13.94 -61.97 -6.73 -59.63 -11.02C-59.63 -11.02 -49.1 -20.77 -49.49 -24.28C-49.49 -24.28 -49.88 -41.83 -51.05 -42.61z"}
++ ,
++ {"fill": "#f2b892",
++  "path":"M-51.5 -41.62C-52.48 -42.54 -59.86 -48.08 -65.56 -42C-65.56 -42 -75.44 -24.9 -74.68 -18.82L-74.68 -16.92C-74.68 -16.92 -81.9 -17.3 -83.42 -15.4C-83.42 -15.4 -84.56 -10.46 -85.7 -10.08C-85.7 -10.08 -88.36 -7.8 -86.46 -5.14C-86.46 -5.14 -88.36 -2.86 -87.98 0.94L-80.76 4.74C-80.76 4.74 -78.86 18.42 -68.6 23.36C-64.006 25.572 -61 19.18 -59.1 13.48C-59.1 13.48 -62.14 -6.66 -59.86 -10.84C-59.86 -10.84 -49.6 -20.34 -49.98 -23.76C-49.98 -23.76 -50.36 -40.86 -51.5 -41.62z"}
++ ,
++ {"fill": "#f8dcc8",
++  "path":"M-51.95 -40.63C-52.82 -41.61 -60.09 -46.92 -65.64 -41C-65.64 -41 -75.26 -24.35 -74.52 -18.43L-74.52 -16.58C-74.52 -16.58 -81.55 -16.95 -83.03 -15.1C-83.03 -15.1 -84.14 -10.29 -85.25 -9.92C-85.25 -9.92 -87.84 -7.7 -85.99 -5.11C-85.99 -5.11 -87.84 -2.89 -87.47 0.81L-80.44 4.51C-80.44 4.51 -78.59 17.83 -68.6 22.64C-64.127 24.794 -61.2 18.57 -59.35 13.02C-59.35 13.02 -62.31 -6.59 -60.09 -10.66C-60.09 -10.66 -50.1 -19.91 -50.47 -23.24C-50.47 -23.24 -50.84 -39.89 -51.95 -40.63z"}
++ ,
++ {"fill": "#ffffff",
++  "path":"M-59.6 12.46C-59.6 12.46 -62.48 -6.52 -60.32 -10.48C-60.32 -10.48 -50.6 -19.48 -50.96 -22.72C-50.96 -22.72 -51.32 -38.92 -52.4 -39.64C-53.16 -40.68 -60.32 -45.76 -65.72 -40C-65.72 -40 -75.08 -23.8 -74.36 -18.04L-74.36 -16.24C-74.36 -16.24 -81.2 -16.6 -82.64 -14.8C-82.64 -14.8 -83.72 -10.12 -84.8 -9.76C-84.8 -9.76 -87.32 -7.6 -85.52 -5.08C-85.52 -5.08 -87.32 -2.92 -86.96 0.68L-80.12 4.28C-80.12 4.28 -78.32 17.24 -68.6 21.92C-64.248 24.015 -61.4 17.86 -59.6 12.46z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-62.7 6.2C-62.7 6.2 -84.3 -4 -85.2 -4.8C-85.2 -4.8 -76.1 3.4 -75.3 3.4C-74.5 3.4 -62.7 6.2 -62.7 6.2z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-79.8 0C-79.8 0 -61.4 3.6 -61.4 8C-61.4 10.912 -61.643 24.331 -67 22.8C-75.4 20.4 -71.8 6 -79.8 0z"}
++ ,
++ {"fill": "#99cc32",
++  "path":"M-71.4 3.8C-71.4 3.8 -62.422 5.274 -61.4 8C-60.8 9.6 -60.137 17.908 -65.6 19C-70.152 19.911 -72.382 9.69 -71.4 3.8z"}
++ ,
++ {"fill": "#000000",
++  "path":"M14.595 46.349C14.098 44.607 15.409 44.738 17.2 44.2C19.2 43.6 31.4 39.8 32.2 37.2C33 34.6 46.2 39 46.2 39C48 39.8 52.4 42.4 52.4 42.4C57.2 43.6 63.8 44 63.8 44C66.2 45 69.6 47.8 69.6 47.8C84.2 58 96.601 50.8 96.601 50.8C116.601 44.2 110.601 27 110.601 27C107.601 18 110.801 14.6 110.801 14.6C111.001 10.8 118.201 17.2 118.201 17.2C120.801 21.4 121.601 26.4 121.601 26.4C129.601 37.6 126.201 19.8 126.201 19.8C126.401 18.8 123.601 15.2 123.601 14C123.601 12.8 121.801 9.4 121.801 9.4C118.801 6 121.201 -1 121.201 -1C123.001 -14.8 120.801 -13 120.801 -13C119.601 -14.8 110.401 -4.8 110.401 -4.8C108.201 -1.4 102.201 0.2 102.201 0.2C99.401 2 96.001 0.6 96.001 0.6C93.401 0.2 87.801 7.2 87.801 7.2C90.601 7 93.001 11.4 95.401 11.6C97.801 11.8 99.601 9.2 101.201 8.6C102.801 8 105.601 13.8 105.601 13.8C106.001 16.4 100.401 21.2 100.401 21.2C100.001 25.8 98.401 24.2 98.401 24.2C95.401 23.6 94.201 27.4 93.201 32C92.201 36.6 88.001 37 88.001 37C86.401 44.4 85.2 41.4 85.2 41.4C85 35.8 79 41.6 79 41.6C77.8 43.6 73.2 41.4 73.2 41.4C66.4 39.4 68.8 37.4 68.8 37.4C70.6 35.2 81.8 37.4 81.8 37.4C84 35.8 76 31.8 76 31.8C75.4 30 76.4 25.6 76.4 25.6C77.6 22.4 84.4 16.8 84.4 16.8C93.801 15.6 91.001 14 91.001 14C84.801 8.8 79 16.4 79 16.4C76.8 22.6 59.4 37.6 59.4 37.6C54.6 41 57.2 34.2 53.2 37.6C49.2 41 28.6 32 28.6 32C17.038 30.807 14.306 46.549 10.777 43.429C10.777 43.429 16.195 51.949 14.595 46.349z"}
++ ,
++ {"fill": "#000000",
++  "path":"M209.401 -120C209.401 -120 183.801 -112 181.001 -93.2C181.001 -93.2 178.601 -70.4 199.001 -52.8C199.001 -52.8 199.401 -46.4 201.401 -43.2C201.401 -43.2 199.801 -38.4 218.601 -46L245.801 -54.4C245.801 -54.4 252.201 -56.8 257.401 -65.6C262.601 -74.4 277.801 -93.2 274.201 -118.4C274.201 -118.4 275.401 -129.6 269.401 -130C269.401 -130 261.001 -131.6 253.801 -124C253.801 -124 247.001 -120.8 244.601 -121.2L209.401 -120z"}
++ ,
++ {"fill": "#000000",
++  "path":"M264.022 -120.99C264.022 -120.99 266.122 -129.92 261.282 -125.08C261.282 -125.08 254.242 -119.36 246.761 -119.36C246.761 -119.36 232.241 -117.16 227.841 -103.96C227.841 -103.96 223.881 -77.12 231.801 -71.4C231.801 -71.4 236.641 -63.92 243.681 -70.52C250.722 -77.12 266.222 -107.35 264.022 -120.99z"}
++ ,
++ {"fill": "#323232",
++  "path":"M263.648 -120.632C263.648 -120.632 265.738 -129.376 260.986 -124.624C260.986 -124.624 254.074 -119.008 246.729 -119.008C246.729 -119.008 232.473 -116.848 228.153 -103.888C228.153 -103.888 224.265 -77.536 232.041 -71.92C232.041 -71.92 236.793 -64.576 243.705 -71.056C250.618 -77.536 265.808 -107.24 263.648 -120.632z"}
++ ,
++ {"fill": "#666666",
++  "path":"M263.274 -120.274C263.274 -120.274 265.354 -128.832 260.69 -124.168C260.69 -124.168 253.906 -118.656 246.697 -118.656C246.697 -118.656 232.705 -116.536 228.465 -103.816C228.465 -103.816 224.649 -77.952 232.281 -72.44C232.281 -72.44 236.945 -65.232 243.729 -71.592C250.514 -77.952 265.394 -107.13 263.274 -120.274z"}
++ ,
++ {"fill": "#999999",
++  "path":"M262.9 -119.916C262.9 -119.916 264.97 -128.288 260.394 -123.712C260.394 -123.712 253.738 -118.304 246.665 -118.304C246.665 -118.304 232.937 -116.224 228.777 -103.744C228.777 -103.744 225.033 -78.368 232.521 -72.96C232.521 -72.96 237.097 -65.888 243.753 -72.128C250.41 -78.368 264.98 -107.02 262.9 -119.916z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M262.526 -119.558C262.526 -119.558 264.586 -127.744 260.098 -123.256C260.098 -123.256 253.569 -117.952 246.633 -117.952C246.633 -117.952 233.169 -115.912 229.089 -103.672C229.089 -103.672 225.417 -78.784 232.761 -73.48C232.761 -73.48 237.249 -66.544 243.777 -72.664C250.305 -78.784 264.566 -106.91 262.526 -119.558z"}
++ ,
++ {"fill": "#ffffff",
++  "path":"M262.151 -119.2C262.151 -119.2 264.201 -127.2 259.801 -122.8C259.801 -122.8 253.401 -117.6 246.601 -117.6C246.601 -117.6 233.401 -115.6 229.401 -103.6C229.401 -103.6 225.801 -79.2 233.001 -74C233.001 -74 237.401 -67.2 243.801 -73.2C250.201 -79.2 264.151 -106.8 262.151 -119.2z"}
++ ,
++ {"fill": "#992600",
++  "path":"M50.6 84C50.6 84 30.2 64.8 22.2 64C22.2 64 -12.2 60 -27 78C-27 78 -9.4 57.6 18.2 63.2C18.2 63.2 -3.4 58.8 -15.8 62C-15.8 62 -32.6 62 -42.2 76L-45 80.8C-45 80.8 -41 66 -22.6 60C-22.6 60 0.2 55.2 11 60C11 60 -10.6 53.2 -20.6 55.2C-20.6 55.2 -51 52.8 -63.8 79.2C-63.8 79.2 -59.8 64.8 -45 57.6C-45 57.6 -31.4 48.8 -11 51.6C-11 51.6 3.4 54.8 8.6 57.2C13.8 59.6 12.6 56.8 4.2 52C4.2 52 -1.4 42 -15.4 42.4C-15.4 42.4 -58.2 46 -68.6 58C-68.6 58 -55 46.8 -44.6 44C-44.6 44 -22.2 36 -13.8 36.8C-13.8 36.8 11 37.8 18.6 33.8C18.6 33.8 7.4 38.8 10.6 42C13.8 45.2 20.6 52.8 20.6 54C20.6 55.2 44.8 77.3 48.4 81.7L50.6 84z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M189 278C189 278 173.5 241.5 161 232C161 232 187 248 190.5 266C190.5 266 190.5 276 189 278z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M236 285.5C236 285.5 209.5 230.5 191 206.5C191 206.5 234.5 244 239.5 270.5L240 276L237 273.5C237 273.5 236.5 282.5 236 285.5z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M292.5 237C292.5 237 230 177.5 228.5 175C228.5 175 289 241 292 248.5C292 248.5 290 239.5 292.5 237z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M104 280.5C104 280.5 123.5 228.5 142.5 251C142.5 251 157.5 261 157 264C157 264 153 257.5 135 258C135 258 116 255 104 280.5z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M294.5 153C294.5 153 249.5 124.5 242 123C230.193 120.639 291.5 152 296.5 162.5C296.5 162.5 298.5 160 294.5 153z"}
++ ,
++ {"fill": "#000000",
++  "path":"M143.801 259.601C143.801 259.601 164.201 257.601 171.001 250.801L175.401 254.401L193.001 216.001L196.601 221.201C196.601 221.201 211.001 206.401 210.201 198.401C209.401 190.401 223.001 204.401 223.001 204.401C223.001 204.401 222.201 192.801 229.401 199.601C229.401 199.601 227.001 184.001 235.401 192.001C235.401 192.001 224.864 161.844 247.401 187.601C253.001 194.001 248.601 187.201 248.601 187.201C248.601 187.201 222.601 139.201 244.201 153.601C244.201 153.601 246.201 130.801 245.001 126.401C243.801 122.001 241.801 99.6 237.001 94.4C232.201 89.2 237.401 87.6 243.001 92.8C243.001 92.8 231.801 68.8 245.001 80.8C245.001 80.8 241.401 65.6 237.001 62.8C237.001 62.8 231.401 45.6 246.601 56.4C246.601 56.4 242.201 44 239.001 40.8C239.001 40.8 227.401 13.2 234.601 18L239.001 21.6C239.001 21.6 232.201 7.6 238.601 12C245.001 16.4 245.001 16 245.001 16C245.001 16 223.801 -17.2 244.201 0.4C244.201 0.4 236.042 -13.518 232.601 -20.4C232.601 -20.4 213.801 -40.8 228.201 -34.4L233.001 -32.8C233.001 -32.8 224.201 -42.8 216.201 -44.4C208.201 -46 218.601 -52.4 225.001 -50.4C231.401 -48.4 247.001 -40.8 247.001 -40.8C247.001 -40.8 259.801 -22 263.801 -21.6C263.801 -21.6 243.801 -29.2 249.801 -21.2C249.801 -21.2 264.201 -7.2 257.001 -7.6C257.001 -7.6 251.001 -0.4 255.801 8.4C255.801 8.4 237.342 -9.991 252.201 15.6L259.001 32C259.001 32 234.601 7.2 245.801 29.2C245.801 29.2 263.001 52.8 265.001 53.2C267.001 53.6 271.401 62.4 271.401 62.4L267.001 60.4L272.201 69.2C272.201 69.2 261.001 57.2 267.001 70.4L272.601 84.8C272.601 84.8 252.201 62.8 265.801 92.4C265.801 92.4 249.401 87.2 258.201 104.4C258.201 104.4 256.601 120.401 257.001 125.601C257.401 130.801 258.601 159.201 254.201 167.201C249.801 175.201 260.201 194.401 262.201 198.401C264.201 202.401 267.801 213.201 259.001 204.001C250.201 194.801 254.601 200.401 256.601 209.201C258.601 218.001 264.601 233.601 263.801 239.201C263.801 239.201 262.601 240.401 259.401 236.801C259.401 236.801 244.601 214.001 246.201 228.401C246.201 228.401 245.001 236.401 241.801 245.201C241.801 245.201 238.601 256.001 238.601 247.201C238.601 247.201 235.401 230.401 232.601 238.001C229.801 245.601 226.201 251.601 223.401 254.001C220.601 256.401 215.401 233.601 214.201 244.001C214.201 244.001 202.201 231.601 197.401 248.001L185.801 264.401C185.801 264.401 185.401 252.001 184.201 258.001C184.201 258.001 154.201 264.001 143.801 259.601z"}
++ ,
++ {"fill": "#000000",
++  "path":"M109.401 -97.2C109.401 -97.2 97.801 -105.2 93.801 -104.8C89.801 -104.4 121.401 -113.6 162.601 -86C162.601 -86 167.401 -83.2 171.001 -83.6C171.001 -83.6 174.201 -81.2 171.401 -77.6C171.401 -77.6 162.601 -68 173.801 -56.8C173.801 -56.8 192.201 -50 186.601 -58.8C186.601 -58.8 197.401 -54.8 199.801 -50.8C202.201 -46.8 201.001 -50.8 201.001 -50.8C201.001 -50.8 194.601 -58 188.601 -63.2C188.601 -63.2 183.401 -65.2 180.601 -73.6C177.801 -82 175.401 -92 179.801 -95.2C179.801 -95.2 175.801 -90.8 176.601 -94.8C177.401 -98.8 181.001 -102.4 182.601 -102.8C184.201 -103.2 200.601 -119 207.401 -119.4C207.401 -119.4 198.201 -118 195.201 -119C192.201 -120 165.601 -131.4 159.601 -132.6C159.601 -132.6 142.801 -139.2 154.801 -137.2C154.801 -137.2 190.601 -133.4 208.801 -120.2C208.801 -120.2 201.601 -128.6 183.201 -135.6C183.201 -135.6 161.001 -148.2 125.801 -143.2C125.801 -143.2 108.001 -140 100.201 -138.2C100.201 -138.2 97.601 -138.8 97.001 -139.2C96.401 -139.6 84.6 -148.6 57 -141.6C57 -141.6 40 -137 31.4 -132.2C31.4 -132.2 16.2 -131 12.6 -127.8C12.6 -127.8 -6 -113.2 -8 -112.4C-10 -111.6 -21.4 -104 -22.2 -103.6C-22.2 -103.6 2.4 -110.2 4.8 -112.6C7.2 -115 24.6 -117.6 27 -116.2C29.4 -114.8 37.8 -115.4 28.2 -114.8C28.2 -114.8 103.801 -100 104.601 -98C105.401 -96 109.401 -97.2 109.401 -97.2z"}
++ ,
++ {"fill": "#cc7226",
++  "path":"M180.801 -106.4C180.801 -106.4 170.601 -113.8 168.601 -113.8C166.601 -113.8 154.201 -124 150.001 -123.6C145.801 -123.2 133.601 -133.2 106.201 -125C106.201 -125 105.601 -127 109.201 -127.8C109.201 -127.8 115.601 -130 116.001 -130.6C116.001 -130.6 136.201 -134.8 143.401 -131.2C143.401 -131.2 152.601 -128.6 158.801 -122.4C158.801 -122.4 170.001 -119.2 173.201 -120.2C173.201 -120.2 182.001 -118 182.401 -116.2C182.401 -116.2 188.201 -113.2 186.401 -110.6C186.401 -110.6 186.801 -109 180.801 -106.4z"}
++ ,
++ {"fill": "#cc7226",
++  "path":"M168.33 -108.509C169.137 -107.877 170.156 -107.779 170.761 -106.97C170.995 -106.656 170.706 -106.33 170.391 -106.233C169.348 -105.916 168.292 -106.486 167.15 -105.898C166.748 -105.691 166.106 -105.873 165.553 -106.022C163.921 -106.463 162.092 -106.488 160.401 -105.8C158.416 -106.929 156.056 -106.345 153.975 -107.346C153.917 -107.373 153.695 -107.027 153.621 -107.054C150.575 -108.199 146.832 -107.916 144.401 -110.2C141.973 -110.612 139.616 -111.074 137.188 -111.754C135.37 -112.263 133.961 -113.252 132.341 -114.084C130.964 -114.792 129.507 -115.314 127.973 -115.686C126.11 -116.138 124.279 -116.026 122.386 -116.546C122.293 -116.571 122.101 -116.227 122.019 -116.254C121.695 -116.362 121.405 -116.945 121.234 -116.892C119.553 -116.37 118.065 -117.342 116.401 -117C115.223 -118.224 113.495 -117.979 111.949 -118.421C108.985 -119.269 105.831 -117.999 102.801 -119C106.914 -120.842 111.601 -119.61 115.663 -121.679C117.991 -122.865 120.653 -121.763 123.223 -122.523C123.71 -122.667 124.401 -122.869 124.801 -122.2C124.935 -122.335 125.117 -122.574 125.175 -122.546C127.625 -121.389 129.94 -120.115 132.422 -119.049C132.763 -118.903 133.295 -119.135 133.547 -118.933C135.067 -117.717 137.01 -117.82 138.401 -116.6C140.099 -117.102 141.892 -116.722 143.621 -117.346C143.698 -117.373 143.932 -117.032 143.965 -117.054C145.095 -117.802 146.25 -117.531 147.142 -117.227C147.48 -117.112 148.143 -116.865 148.448 -116.791C149.574 -116.515 150.43 -116.035 151.609 -115.852C151.723 -115.834 151.908 -116.174 151.98 -116.146C153.103 -115.708 154.145 -115.764 154.801 -114.6C154.936 -114.735 155.101 -114.973 155.183 -114.946C156.21 -114.608 156.859 -113.853 157.96 -113.612C158.445 -113.506 159.057 -112.88 159.633 -112.704C162.025 -111.973 163.868 -110.444 166.062 -109.549C166.821 -109.239 167.697 -109.005 168.33 -108.509z"}
++ ,
++ {"fill": "#cc7226",
++  "path":"M91.696 -122.739C89.178 -124.464 86.81 -125.57 84.368 -127.356C84.187 -127.489 83.827 -127.319 83.625 -127.441C82.618 -128.05 81.73 -128.631 80.748 -129.327C80.209 -129.709 79.388 -129.698 78.88 -129.956C76.336 -131.248 73.707 -131.806 71.2 -133C71.882 -133.638 73.004 -133.394 73.6 -134.2C73.795 -133.92 74.033 -133.636 74.386 -133.827C76.064 -134.731 77.914 -134.884 79.59 -134.794C81.294 -134.702 83.014 -134.397 84.789 -134.125C85.096 -134.078 85.295 -133.555 85.618 -133.458C87.846 -132.795 90.235 -133.32 92.354 -132.482C93.945 -131.853 95.515 -131.03 96.754 -129.755C97.006 -129.495 96.681 -129.194 96.401 -129C96.789 -129.109 97.062 -128.903 97.173 -128.59C97.257 -128.351 97.257 -128.049 97.173 -127.81C97.061 -127.498 96.782 -127.397 96.408 -127.346C95.001 -127.156 96.773 -128.536 96.073 -128.088C94.8 -127.274 95.546 -125.868 94.801 -124.6C94.521 -124.794 94.291 -125.012 94.401 -125.4C94.635 -124.878 94.033 -124.588 93.865 -124.272C93.48 -123.547 92.581 -122.132 91.696 -122.739z"}
++ ,
++ {"fill": "#cc7226",
++  "path":"M59.198 -115.391C56.044 -116.185 52.994 -116.07 49.978 -117.346C49.911 -117.374 49.688 -117.027 49.624 -117.054C48.258 -117.648 47.34 -118.614 46.264 -119.66C45.351 -120.548 43.693 -120.161 42.419 -120.648C42.095 -120.772 41.892 -121.284 41.591 -121.323C40.372 -121.48 39.445 -122.429 38.4 -123C40.736 -123.795 43.147 -123.764 45.609 -124.148C45.722 -124.166 45.867 -123.845 46 -123.845C46.136 -123.845 46.266 -124.066 46.4 -124.2C46.595 -123.92 46.897 -123.594 47.154 -123.848C47.702 -124.388 48.258 -124.198 48.798 -124.158C48.942 -124.148 49.067 -123.845 49.2 -123.845C49.336 -123.845 49.467 -124.156 49.6 -124.156C49.736 -124.155 49.867 -123.845 50 -123.845C50.136 -123.845 50.266 -124.066 50.4 -124.2C51.092 -123.418 51.977 -123.972 52.799 -123.793C53.837 -123.566 54.104 -122.418 55.178 -122.12C59.893 -120.816 64.03 -118.671 68.393 -116.584C68.7 -116.437 68.91 -116.189 68.8 -115.8C69.067 -115.8 69.38 -115.888 69.57 -115.756C70.628 -115.024 71.669 -114.476 72.366 -113.378C72.582 -113.039 72.253 -112.632 72.02 -112.684C67.591 -113.679 63.585 -114.287 59.198 -115.391z"}
++ ,
++ {"fill": "#cc7226",
++  "path":"M45.338 -71.179C43.746 -72.398 43.162 -74.429 42.034 -76.221C41.82 -76.561 42.094 -76.875 42.411 -76.964C42.971 -77.123 43.514 -76.645 43.923 -76.443C45.668 -75.581 47.203 -74.339 49.2 -74.2C51.19 -71.966 55.45 -71.581 55.457 -68.2C55.458 -67.341 54.03 -68.259 53.6 -67.4C51.149 -68.403 48.76 -68.3 46.38 -69.767C45.763 -70.148 46.093 -70.601 45.338 -71.179z"}
++ ,
++ {"fill": "#cc7226",
++  "path":"M17.8 -123.756C17.935 -123.755 24.966 -123.522 24.949 -123.408C24.904 -123.099 17.174 -122.05 16.81 -122.22C16.646 -122.296 9.134 -119.866 9 -120C9.268 -120.135 17.534 -123.756 17.8 -123.756z"}
++ ,
++ {"fill": "#000000",
++  "path":"M33.2 -114C33.2 -114 18.4 -112.2 14 -111C9.6 -109.8 -9 -102.2 -12 -100.2C-12 -100.2 -25.4 -94.8 -42.4 -74.8C-42.4 -74.8 -34.8 -78.2 -32.6 -81C-32.6 -81 -19 -93.6 -19.2 -91C-19.2 -91 -7 -99.6 -7.6 -97.4C-7.6 -97.4 16.8 -108.6 14.8 -105.4C14.8 -105.4 36.4 -110 35.4 -108C35.4 -108 54.2 -103.6 51.4 -103.4C51.4 -103.4 45.6 -102.2 52 -98.6C52 -98.6 48.6 -94.2 43.2 -98.2C37.8 -102.2 40.8 -100 35.8 -99C35.8 -99 33.2 -98.2 28.6 -102.2C28.6 -102.2 23 -106.8 14.2 -103.2C14.2 -103.2 -16.4 -90.6 -18.4 -90C-18.4 -90 -22 -87.2 -24.4 -83.6C-24.4 -83.6 -30.2 -79.2 -33.2 -77.8C-33.2 -77.8 -46 -66.2 -47.2 -64.8C-47.2 -64.8 -50.6 -59.6 -51.4 -59.2C-51.4 -59.2 -45 -63 -43 -65C-43 -65 -29 -75 -23.6 -75.8C-23.6 -75.8 -19.2 -78.8 -18.4 -80.2C-18.4 -80.2 -4 -89.4 0.2 -89.4C0.2 -89.4 9.4 -84.2 11.8 -91.2C11.8 -91.2 17.6 -93 23.2 -91.8C23.2 -91.8 26.4 -94.4 25.6 -96.6C25.6 -96.6 27.2 -98.4 28.2 -94.6C28.2 -94.6 31.6 -91 36.4 -93C36.4 -93 40.4 -93.2 38.4 -90.8C38.4 -90.8 34 -87 22.2 -86.8C22.2 -86.8 9.8 -86.2 -6.6 -78.6C-6.6 -78.6 -36.4 -68.2 -45.6 -57.8C-45.6 -57.8 -52 -49 -57.4 -47.8C-57.4 -47.8 -63.2 -47 -69.2 -39.6C-69.2 -39.6 -59.4 -45.4 -50.4 -45.4C-50.4 -45.4 -46.4 -47.8 -50.2 -44.2C-50.2 -44.2 -53.8 -36.6 -52.2 -31.2C-52.2 -31.2 -52.8 -26 -53.6 -24.4C-53.6 -24.4 -61.4 -11.6 -61.4 -9.2C-61.4 -6.8 -60.2 3 -59.8 3.6C-59.4 4.2 -60.8 2 -57 4.4C-53.2 6.8 -50.4 8.4 -49.6 11.2C-48.8 14 -51.6 5.8 -51.8 4C-52 2.2 -56.2 -5 -55.4 -7.4C-55.4 -7.4 -54.4 -6.4 -53.6 -5C-53.6 -5 -54.2 -5.6 -53.6 -9.2C-53.6 -9.2 -52.8 -14.4 -51.4 -17.6C-50 -20.8 -48 -24.6 -47.6 -25.4C-47.2 -26.2 -47.2 -32 -45.8 -29.4L-42.4 -26.8C-42.4 -26.8 -45.2 -29.4 -43 -31.6C-43 -31.6 -44 -37.2 -42.2 -39.8C-42.2 -39.8 -35.2 -48.2 -33.6 -49.2C-32 -50.2 -33.4 -49.8 -33.4 -49.8C-33.4 -49.8 -27.4 -54 -33.2 -52.4C-33.2 -52.4 -37.2 -50.8 -40.2 -50.8C-40.2 -50.8 -47.8 -48.8 -43.8 -53C-39.8 -57.2 -29.8 -62.6 -26 -62.4L-25.2 -60.8L-14 -63.2L-15.2 -62.4C-15.2 -62.4 -15.4 -62.6 -11.2 -63C-7 -63.4 -1.2 -62 0.2 -63.8C1.6 -65.6 5 -66.6 4.6 -65.2C4.2 -63.8 4 -61.8 4 -61.8C4 -61.8 9 -67.6 8.4 -65.4C7.8 -63.2 -0.4 -58 -1.8 -51.8L8.6 -60L12.2 -63C12.2 -63 15.8 -60.8 16 -62.4C16.2 -64 20.8 -69.8 22 -69.6C23.2 -69.4 25.2 -72.2 25 -69.6C24.8 -67 32.4 -61.6 32.4 -61.6C32.4 -61.6 35.6 -63.4 37 -62C38.4 -60.6 42.6 -81.8 42.6 -81.8L67.6 -92.4L111.201 -95.8L94.201 -102.6L33.2 -114z"}
++ ,
++ {"stroke":"#4c0000", "width":2,
++  "path":"M51.4 85C51.4 85 36.4 68.2 28 65.6C28 65.6 14.6 58.8 -10 66.6"}
++ ,
++ {"stroke":"#4c0000", "width":2,
++  "path":"M24.8 64.2C24.8 64.2 -0.4 56.2 -15.8 60.4C-15.8 60.4 -34.2 62.4 -42.6 76.2"}
++ ,
++ {"stroke":"#4c0000", "width":2,
++  "path":"M21.2 63C21.2 63 4.2 55.8 -10.6 53.6C-10.6 53.6 -27.2 51 -43.8 58.2C-43.8 58.2 -56 64.2 -61.4 74.4"}
++ ,
++ {"stroke":"#4c0000", "width":2,
++  "path":"M22.2 63.4C22.2 63.4 6.8 52.4 5.8 51C5.8 51 -1.2 40 -14.2 39.6C-14.2 39.6 -35.6 40.4 -52.8 48.4"}
++ ,
++ {"fill": "#000000",
++  "path":"M20.895 54.407C22.437 55.87 49.4 84.8 49.4 84.8C84.6 121.401 56.6 87.2 56.6 87.2C49 82.4 39.8 63.6 39.8 63.6C38.6 60.8 53.8 70.8 53.8 70.8C57.8 71.6 71.4 90.8 71.4 90.8C64.6 88.4 69.4 95.6 69.4 95.6C72.2 97.6 92.601 113.201 92.601 113.201C96.201 117.201 100.201 118.801 100.201 118.801C114.201 113.601 107.801 126.801 107.801 126.801C110.201 133.601 115.801 122.001 115.801 122.001C127.001 105.2 110.601 107.601 110.601 107.601C80.6 110.401 73.8 94.4 73.8 94.4C71.4 92 80.2 94.4 80.2 94.4C88.601 96.4 73 82 73 82C75.4 82 84.6 88.8 84.6 88.8C95.001 98 97.001 96 97.001 96C115.001 87.2 125.401 94.8 125.401 94.8C127.401 96.4 121.801 103.2 123.401 108.401C125.001 113.601 129.801 126.001 129.801 126.001C127.401 127.601 127.801 138.401 127.801 138.401C144.601 161.601 135.001 159.601 135.001 159.601C119.401 159.201 134.201 166.801 134.201 166.801C137.401 168.801 146.201 176.001 146.201 176.001C143.401 174.801 141.801 180.001 141.801 180.001C146.601 184.001 143.801 188.801 143.801 188.801C137.801 190.001 136.601 194.001 136.601 194.001C143.401 202.001 133.401 202.401 133.401 202.401C137.001 206.801 132.201 218.801 132.201 218.801C127.401 218.801 121.001 224.401 121.001 224.401C123.401 229.201 113.001 234.801 113.001 234.801C104.601 236.401 107.401 243.201 107.401 243.201C99.401 249.201 97.001 265.201 97.001 265.201C96.201 275.601 93.801 278.801 99.001 276.801C104.201 274.801 103.401 262.401 103.401 262.401C98.601 246.801 141.401 230.801 141.401 230.801C145.401 229.201 146.201 224.001 146.201 224.001C148.201 224.401 157.001 232.001 157.001 232.001C164.601 243.201 165.001 234.001 165.001 234.001C166.201 230.401 164.601 224.401 164.601 224.401C170.601 202.801 156.601 196.401 156.601 196.401C146.601 162.801 160.601 171.201 160.601 171.201C163.401 176.801 174.201 182.001 174.201 182.001L177.801 179.601C176.201 174.801 184.601 168.801 184.601 168.801C187.401 175.201 193.401 167.201 193.401 167.201C197.001 142.801 209.401 157.201 209.401 157.201C213.401 158.401 214.601 151.601 214.601 151.601C218.201 141.201 214.601 127.601 214.601 127.601C218.201 127.201 227.801 133.201 227.801 133.201C230.601 129.601 221.401 112.801 225.401 115.201C229.401 117.601 233.801 119.201 233.801 119.201C234.601 117.201 224.601 104.801 224.601 104.801C220.201 102 215.001 81.6 215.001 81.6C222.201 85.2 212.201 70 212.201 70C212.201 66.8 218.201 55.6 218.201 55.6C217.401 48.8 218.201 49.2 218.201 49.2C221.001 50.4 229.001 52 222.201 45.6C215.401 39.2 223.001 34.4 223.001 34.4C227.401 31.6 213.801 32 213.801 32C208.601 27.6 209.001 23.6 209.001 23.6C217.001 25.6 202.601 11.2 200.201 7.6C197.801 4 207.401 -1.2 207.401 -1.2C220.601 -4.8 209.001 -8 209.001 -8C189.401 -7.6 200.201 -18.4 200.201 -18.4C206.201 -18 204.601 -20.4 204.601 -20.4C199.401 -21.6 189.801 -28 189.801 -28C185.801 -31.6 189.401 -30.8 189.401 -30.8C206.201 -29.6 177.401 -40.8 177.401 -40.8C185.401 -40.8 167.401 -51.2 167.401 -51.2C165.401 -52.8 162.201 -60.4 162.201 -60.4C156.201 -65.6 151.401 -72.4 151.401 -72.4C151.001 -76.8 146.201 -81.6 146.201 -81.6C134.601 -95.2 129.001 -94.8 129.001 -94.8C114.201 -98.4 109.001 -97.6 109.001 -97.6L56.2 -93.2C29.8 -80.4 37.6 -59.4 37.6 -59.4C44 -51 53.2 -54.8 53.2 -54.8C57.8 -61 69.4 -58.8 69.4 -58.8C89.801 -55.6 87.201 -59.2 87.201 -59.2C84.801 -63.8 68.6 -70 68.4 -70.6C68.2 -71.2 59.4 -74.6 59.4 -74.6C56.4 -75.8 52 -85 52 -85C48.8 -88.4 64.6 -82.6 64.6 -82.6C63.4 -81.6 70.8 -77.6 70.8 -77.6C88.201 -78.6 98.801 -67.8 98.801 -67.8C109.601 -51.2 109.801 -59.4 109.801 -59.4C112.601 -68.8 100.801 -90 100.801 -90C101.201 -92 109.401 -85.4 109.401 -85.4C110.801 -87.4 111.601 -81.6 111.601 -81.6C111.801 -79.2 115.601 -71.2 115.601 -71.2C118.401 -58.2 122.001 -65.6 122.001 -65.6L126.601 -56.2C128.001 -53.6 122.001 -46 122.001 -46C121.801 -43.2 122.601 -43.4 117.001 -35.8C111.401 -28.2 114.801 -23.8 114.801 -23.8C113.401 -17.2 122.201 -17.6 122.201 -17.6C124.801 -15.4 128.201 -15.4 128.201 -15.4C130.001 -13.4 132.401 -14 132.401 -14C134.001 -17.8 140.201 -15.8 140.201 -15.8C141.601 -18.2 149.801 -18.6 149.801 -18.6C150.801 -21.2 151.201 -22.8 154.601 -23.4C158.001 -24 133.401 -67 133.401 -67C139.801 -67.8 131.601 -80.2 131.601 -80.2C129.401 -86.8 140.801 -72.2 143.001 -70.8C145.201 -69.4 146.201 -67.2 144.601 -67.4C143.001 -67.6 141.201 -65.4 142.601 -65.2C144.001 -65 157.001 -50 160.401 -39.8C163.801 -29.6 169.801 -25.6 176.001 -19.6C182.201 -13.6 181.401 10.6 181.401 10.6C181.001 19.4 187.001 30 187.001 30C189.001 33.8 184.801 52 184.801 52C182.801 54.2 184.201 55 184.201 55C185.201 56.2 192.001 69.4 192.001 69.4C190.201 69.2 193.801 72.8 193.801 72.8C199.001 78.8 192.601 75.8 192.601 75.8C186.601 74.2 193.601 84 193.601 84C194.801 85.8 185.801 81.2 185.801 81.2C176.601 80.6 188.201 87.8 188.201 87.8C196.801 95 185.401 90.6 185.401 90.6C180.801 88.8 184.001 95.6 184.001 95.6C187.201 97.2 204.401 104.2 204.401 104.2C204.801 108.001 201.801 113.001 201.801 113.001C202.201 117.001 200.001 120.401 200.001 120.401C198.801 128.601 198.201 129.401 198.201 129.401C194.001 129.601 186.601 143.401 186.601 143.401C184.801 146.001 174.601 158.001 174.601 158.001C172.601 165.001 154.601 157.801 154.601 157.801C148.001 161.201 150.001 157.801 150.001 157.801C149.601 155.601 154.401 149.601 154.401 149.601C161.401 147.001 158.801 136.201 158.801 136.201C162.801 134.801 151.601 132.001 151.801 130.801C152.001 129.601 157.801 128.201 157.801 128.201C165.801 126.201 161.401 123.801 161.401 123.801C160.801 119.801 163.801 114.201 163.801 114.201C175.401 113.401 163.801 97.2 163.801 97.2C153.001 89.6 152.001 83.8 152.001 83.8C164.601 75.6 156.401 63.2 156.601 59.6C156.801 56 158.001 34.4 158.001 34.4C156.001 28.2 153.001 14.6 153.001 14.6C155.201 9.4 162.601 -3.2 162.601 -3.2C165.401 -7.4 174.201 -12.2 172.001 -15.2C169.801 -18.2 162.001 -16.4 162.001 -16.4C154.201 -17.8 154.801 -12.6 154.801 -12.6C153.201 -11.6 152.401 -6.6 152.401 -6.6C151.68 1.333 142.801 7.6 142.801 7.6C131.601 13.8 140.801 17.8 140.801 17.8C146.801 24.4 137.001 24.6 137.001 24.6C126.001 22.8 134.201 33 134.201 33C145.001 45.8 142.001 48.6 142.001 48.6C131.801 49.6 144.401 58.8 144.401 58.8C144.401 58.8 143.601 56.8 143.801 58.6C144.001 60.4 147.001 64.6 147.801 66.6C148.601 68.6 144.601 68.8 144.601 68.8C145.201 78.4 129.801 74.2 129.801 74.2C129.801 74.2 129.801 74.2 128.201 74.4C126.601 74.6 115.401 73.8 109.601 71.6C103.801 69.4 97.001 69.4 97.001 69.4C97.001 69.4 93.001 71.2 85.4 71C77.8 70.8 69.8 73.6 69.8 73.6C65.4 73.2 74 68.8 74.2 69C74.4 69.2 80 63.6 72 64.2C50.203 65.835 39.4 55.6 39.4 55.6C37.4 54.2 34.8 51.4 34.8 51.4C24.8 49.4 36.2 63.8 36.2 63.8C37.4 65.2 36 66.2 36 66.2C35.2 64.6 27.4 59.2 27.4 59.2C24.589 58.227 23.226 56.893 20.895 54.407z"}
++ ,
++ {"fill": "#4c0000",
++  "path":"M-3 42.8C-3 42.8 8.6 48.4 11.2 51.2C13.8 54 27.8 65.4 27.8 65.4C27.8 65.4 22.4 63.4 19.8 61.6C17.2 59.8 6.4 51.6 6.4 51.6C6.4 51.6 2.6 45.6 -3 42.8z"}
++ ,
++ {"fill": "#99cc32",
++  "path":"M-61.009 11.603C-60.672 11.455 -61.196 8.743 -61.4 8.2C-62.422 5.474 -71.4 4 -71.4 4C-71.627 5.365 -71.682 6.961 -71.576 8.599C-71.576 8.599 -66.708 14.118 -61.009 11.603z"}
++ ,
++ {"fill": "#659900",
++  "path":"M-61.009 11.403C-61.458 11.561 -61.024 8.669 -61.2 8.2C-62.222 5.474 -71.4 3.9 -71.4 3.9C-71.627 5.265 -71.682 6.861 -71.576 8.499C-71.576 8.499 -67.308 13.618 -61.009 11.403z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-65.4 11.546C-66.025 11.546 -66.531 10.406 -66.531 9C-66.531 7.595 -66.025 6.455 -65.4 6.455C-64.775 6.455 -64.268 7.595 -64.268 9C-64.268 10.406 -64.775 11.546 -65.4 11.546z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-65.4 9z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-111 109.601C-111 109.601 -116.6 119.601 -91.8 113.601C-91.8 113.601 -77.8 112.401 -75.4 110.001C-74.2 110.801 -65.834 113.734 -63 114.401C-56.2 116.001 -47.8 106 -47.8 106C-47.8 106 -43.2 95.5 -40.4 95.5C-37.6 95.5 -40.8 97.1 -40.8 97.1C-40.8 97.1 -47.4 107.201 -47 108.801C-47 108.801 -52.2 128.801 -68.2 129.601C-68.2 129.601 -84.35 130.551 -83 136.401C-83 136.401 -74.2 134.001 -71.8 136.401C-71.8 136.401 -61 136.001 -69 142.401L-75.8 154.001C-75.8 154.001 -75.66 157.919 -85.8 154.401C-95.6 151.001 -105.9 138.101 -105.9 138.101C-105.9 138.101 -121.85 123.551 -111 109.601z"}
++ ,
++ {"fill": "#e59999",
++  "path":"M-112.2 113.601C-112.2 113.601 -114.2 123.201 -77.4 112.801C-77.4 112.801 -73 112.801 -70.6 113.601C-68.2 114.401 -56.2 117.201 -54.2 116.001C-54.2 116.001 -61.4 129.601 -73 128.001C-73 128.001 -86.2 129.601 -85.8 134.401C-85.8 134.401 -81.8 141.601 -77 144.001C-77 144.001 -74.2 146.401 -74.6 149.601C-75 152.801 -77.8 154.401 -79.8 155.201C-81.8 156.001 -85 152.801 -86.6 152.801C-88.2 152.801 -96.6 146.401 -101 141.601C-105.4 136.801 -113.8 124.801 -113.4 122.001C-113 119.201 -112.2 113.601 -112.2 113.601z"}
++ ,
++ {"fill": "#b26565",
++  "path":"M-109 131.051C-106.4 135.001 -103.2 139.201 -101 141.601C-96.6 146.401 -88.2 152.801 -86.6 152.801C-85 152.801 -81.8 156.001 -79.8 155.201C-77.8 154.401 -75 152.801 -74.6 149.601C-74.2 146.401 -77 144.001 -77 144.001C-80.066 142.468 -82.806 138.976 -84.385 136.653C-84.385 136.653 -84.2 139.201 -89.4 138.401C-94.6 137.601 -99.8 134.801 -101.4 131.601C-103 128.401 -105.4 126.001 -103.8 129.601C-102.2 133.201 -99.8 136.801 -98.2 137.201C-96.6 137.601 -97 138.801 -99.4 138.401C-101.8 138.001 -104.6 137.601 -109 132.401z"}
++ ,
++ {"fill": "#992600",
++  "path":"M-111.6 110.001C-111.6 110.001 -109.8 96.4 -108.6 92.4C-108.6 92.4 -109.4 85.6 -107 81.4C-104.6 77.2 -102.6 71 -99.6 65.6C-96.6 60.2 -96.4 56.2 -92.4 54.6C-88.4 53 -82.4 44.4 -79.6 43.4C-76.8 42.4 -77 43.2 -77 43.2C-77 43.2 -70.2 28.4 -56.6 32.4C-56.6 32.4 -72.8 29.6 -57 20.2C-57 20.2 -61.8 21.3 -58.5 14.3C-56.299 9.632 -56.8 16.4 -67.8 28.2C-67.8 28.2 -72.8 36.8 -78 39.8C-83.2 42.8 -95.2 49.8 -96.4 53.6C-97.6 57.4 -100.8 63.2 -102.8 64.8C-104.8 66.4 -107.6 70.6 -108 74C-108 74 -109.2 78 -110.6 79.2C-112 80.4 -112.2 83.6 -112.2 85.6C-112.2 87.6 -114.2 90.4 -114 92.8C-114 92.8 -113.2 111.801 -113.6 113.801L-111.6 110.001z"}
++ ,
++ {"fill": "#ffffff",
++  "path":"M-120.2 114.601C-120.2 114.601 -122.2 113.201 -126.6 119.201C-126.6 119.201 -119.3 152.201 -119.3 153.601C-119.3 153.601 -118.2 151.501 -119.5 144.301C-120.8 137.101 -121.7 124.401 -121.7 124.401L-120.2 114.601z"}
++ ,
++ {"fill": "#992600",
++  "path":"M-98.6 54C-98.6 54 -116.2 57.2 -115.8 86.4L-116.6 111.201C-116.6 111.201 -117.8 85.6 -119 84C-120.2 82.4 -116.2 71.2 -119.4 77.2C-119.4 77.2 -133.4 91.2 -125.4 112.401C-125.4 112.401 -123.9 115.701 -126.9 111.101C-126.9 111.101 -131.5 98.5 -130.4 92.1C-130.4 92.1 -130.2 89.9 -128.3 87.1C-128.3 87.1 -119.7 75.4 -117 73.1C-117 73.1 -115.2 58.7 -99.8 53.5C-99.8 53.5 -94.1 51.2 -98.6 54z"}
++ ,
++ {"fill": "#000000",
++  "path":"M40.8 -12.2C41.46 -12.554 41.451 -13.524 42.031 -13.697C43.18 -14.041 43.344 -15.108 43.862 -15.892C44.735 -17.211 44.928 -18.744 45.51 -20.235C45.782 -20.935 45.809 -21.89 45.496 -22.55C44.322 -25.031 43.62 -27.48 42.178 -29.906C41.91 -30.356 41.648 -31.15 41.447 -31.748C40.984 -33.132 39.727 -34.123 38.867 -35.443C38.579 -35.884 39.104 -36.809 38.388 -36.893C37.491 -36.998 36.042 -37.578 35.809 -36.552C35.221 -33.965 36.232 -31.442 37.2 -29C36.418 -28.308 36.752 -27.387 36.904 -26.62C37.614 -23.014 36.416 -19.662 35.655 -16.188C35.632 -16.084 35.974 -15.886 35.946 -15.824C34.724 -13.138 33.272 -10.693 31.453 -8.312C30.695 -7.32 29.823 -6.404 29.326 -5.341C28.958 -4.554 28.55 -3.588 28.8 -2.6C25.365 0.18 23.115 4.025 20.504 7.871C20.042 8.551 20.333 9.76 20.884 10.029C21.697 10.427 22.653 9.403 23.123 8.557C23.512 7.859 23.865 7.209 24.356 6.566C24.489 6.391 24.31 5.972 24.445 5.851C27.078 3.504 28.747 0.568 31.2 -1.8C33.15 -2.129 34.687 -3.127 36.435 -4.14C36.743 -4.319 37.267 -4.07 37.557 -4.265C39.31 -5.442 39.308 -7.478 39.414 -9.388C39.464 -10.272 39.66 -11.589 40.8 -12.2z"}
++ ,
++ {"fill": "#000000",
++  "path":"M31.959 -16.666C32.083 -16.743 31.928 -17.166 32.037 -17.382C32.199 -17.706 32.602 -17.894 32.764 -18.218C32.873 -18.434 32.71 -18.814 32.846 -18.956C35.179 -21.403 35.436 -24.427 34.4 -27.4C35.424 -28.02 35.485 -29.282 35.06 -30.129C34.207 -31.829 34.014 -33.755 33.039 -35.298C32.237 -36.567 30.659 -37.811 29.288 -36.508C28.867 -36.108 28.546 -35.321 28.824 -34.609C28.888 -34.446 29.173 -34.3 29.146 -34.218C29.039 -33.894 28.493 -33.67 28.487 -33.398C28.457 -31.902 27.503 -30.391 28.133 -29.062C28.905 -27.433 29.724 -25.576 30.4 -23.8C29.166 -21.684 30.199 -19.235 28.446 -17.358C28.31 -17.212 28.319 -16.826 28.441 -16.624C28.733 -16.138 29.139 -15.732 29.625 -15.44C29.827 -15.319 30.175 -15.317 30.375 -15.441C30.953 -15.803 31.351 -16.29 31.959 -16.666z"}
++ ,
++ {"fill": "#000000",
++  "path":"M94.771 -26.977C96.16 -25.185 96.45 -22.39 94.401 -21C94.951 -17.691 98.302 -19.67 100.401 -20.2C100.292 -20.588 100.519 -20.932 100.802 -20.937C101.859 -20.952 102.539 -21.984 103.601 -21.8C104.035 -23.357 105.673 -24.059 106.317 -25.439C108.043 -29.134 107.452 -33.407 104.868 -36.653C104.666 -36.907 104.883 -37.424 104.759 -37.786C104.003 -39.997 101.935 -40.312 100.001 -41C98.824 -44.875 98.163 -48.906 96.401 -52.6C94.787 -52.85 94.089 -54.589 92.752 -55.309C91.419 -56.028 90.851 -54.449 90.892 -53.403C90.899 -53.198 91.351 -52.974 91.181 -52.609C91.105 -52.445 90.845 -52.334 90.845 -52.2C90.846 -52.065 91.067 -51.934 91.201 -51.8C90.283 -50.98 88.86 -50.503 88.565 -49.358C87.611 -45.648 90.184 -42.523 91.852 -39.322C92.443 -38.187 91.707 -36.916 90.947 -35.708C90.509 -35.013 90.617 -33.886 90.893 -33.03C91.645 -30.699 93.236 -28.96 94.771 -26.977z"}
++ ,
++ {"fill": "#000000",
++  "path":"M57.611 -8.591C56.124 -6.74 52.712 -4.171 55.629 -2.243C55.823 -2.114 56.193 -2.11 56.366 -2.244C58.387 -3.809 60.39 -4.712 62.826 -5.294C62.95 -5.323 63.224 -4.856 63.593 -5.017C65.206 -5.72 67.216 -5.662 68.4 -7C72.167 -6.776 75.732 -7.892 79.123 -9.2C80.284 -9.648 81.554 -10.207 82.755 -10.709C84.131 -11.285 85.335 -12.213 86.447 -13.354C86.58 -13.49 86.934 -13.4 87.201 -13.4C87.161 -14.263 88.123 -14.39 88.37 -15.012C88.462 -15.244 88.312 -15.64 88.445 -15.742C90.583 -17.372 91.503 -19.39 90.334 -21.767C90.049 -22.345 89.8 -22.963 89.234 -23.439C88.149 -24.35 87.047 -23.496 86 -23.8C85.841 -23.172 85.112 -23.344 84.726 -23.146C83.867 -22.707 82.534 -23.292 81.675 -22.854C80.313 -22.159 79.072 -21.99 77.65 -21.613C77.338 -21.531 76.56 -21.627 76.4 -21C76.266 -21.134 76.118 -21.368 76.012 -21.346C74.104 -20.95 72.844 -20.736 71.543 -19.044C71.44 -18.911 70.998 -19.09 70.839 -18.955C69.882 -18.147 69.477 -16.913 68.376 -16.241C68.175 -16.118 67.823 -16.286 67.629 -16.157C66.983 -15.726 66.616 -15.085 65.974 -14.638C65.645 -14.409 65.245 -14.734 65.277 -14.99C65.522 -16.937 66.175 -18.724 65.6 -20.6C67.677 -23.12 70.194 -25.069 72 -27.8C72.015 -29.966 72.707 -32.112 72.594 -34.189C72.584 -34.382 72.296 -35.115 72.17 -35.462C71.858 -36.316 72.764 -37.382 71.92 -38.106C70.516 -39.309 69.224 -38.433 68.4 -37C66.562 -36.61 64.496 -35.917 62.918 -37.151C61.911 -37.938 61.333 -38.844 60.534 -39.9C59.549 -41.202 59.884 -42.638 59.954 -44.202C59.96 -44.33 59.645 -44.466 59.645 -44.6C59.646 -44.735 59.866 -44.866 60 -45C59.294 -45.626 59.019 -46.684 58 -47C58.305 -48.092 57.629 -48.976 56.758 -49.278C54.763 -49.969 53.086 -48.057 51.194 -47.984C50.68 -47.965 50.213 -49.003 49.564 -49.328C49.132 -49.544 48.428 -49.577 48.066 -49.311C47.378 -48.807 46.789 -48.693 46.031 -48.488C44.414 -48.052 43.136 -46.958 41.656 -46.103C40.171 -45.246 39.216 -43.809 38.136 -42.489C37.195 -41.337 37.059 -38.923 38.479 -38.423C40.322 -37.773 41.626 -40.476 43.592 -40.15C43.904 -40.099 44.11 -39.788 44 -39.4C44.389 -39.291 44.607 -39.52 44.8 -39.8C45.658 -38.781 46.822 -38.444 47.76 -37.571C48.73 -36.667 50.476 -37.085 51.491 -36.088C53.02 -34.586 52.461 -31.905 54.4 -30.6C53.814 -29.287 53.207 -28.01 52.872 -26.583C52.59 -25.377 53.584 -24.18 54.795 -24.271C56.053 -24.365 56.315 -25.124 56.8 -26.2C57.067 -25.933 57.536 -25.636 57.495 -25.42C57.038 -23.033 56.011 -21.04 55.553 -18.609C55.494 -18.292 55.189 -18.09 54.8 -18.2C54.332 -14.051 50.28 -11.657 47.735 -8.492C47.332 -7.99 47.328 -6.741 47.737 -6.338C49.14 -4.951 51.1 -6.497 52.8 -7C53.013 -8.206 53.872 -9.148 55.204 -9.092C55.46 -9.082 55.695 -9.624 56.019 -9.754C56.367 -9.892 56.869 -9.668 57.155 -9.866C58.884 -11.061 60.292 -12.167 62.03 -13.356C62.222 -13.487 62.566 -13.328 62.782 -13.436C63.107 -13.598 63.294 -13.985 63.617 -14.17C63.965 -14.37 64.207 -14.08 64.4 -13.8C63.754 -13.451 63.75 -12.494 63.168 -12.292C62.393 -12.024 61.832 -11.511 61.158 -11.064C60.866 -10.871 60.207 -11.119 60.103 -10.94C59.505 -9.912 58.321 -9.474 57.611 -8.591z"}
++ ,
++ {"fill": "#000000",
++  "path":"M2.2 -58C2.2 -58 -7.038 -60.872 -18.2 -35.2C-18.2 -35.2 -20.6 -30 -23 -28C-25.4 -26 -36.6 -22.4 -38.6 -18.4L-49 -2.4C-49 -2.4 -34.2 -18.4 -31 -20.8C-31 -20.8 -23 -29.2 -26.2 -22.4C-26.2 -22.4 -40.2 -11.6 -39 -2.4C-39 -2.4 -44.6 12 -45.4 14C-45.4 14 -29.4 -18 -27 -19.2C-24.6 -20.4 -23.4 -20.4 -24.6 -16.8C-25.8 -13.2 -26.2 3.2 -29 5.2C-29 5.2 -21 -15.2 -21.8 -18.4C-21.8 -18.4 -18.6 -22 -16.2 -16.8L-17.4 -0.8L-13 11.2C-13 11.2 -15.4 0 -13.8 -15.6C-13.8 -15.6 -15.8 -26 -11.8 -20.4C-7.8 -14.8 1.8 -8.8 1.8 -4C1.8 -4 -3.4 -21.6 -12.6 -26.4L-16.6 -20.4L-17.8 -22.4C-17.8 -22.4 -21.4 -23.2 -17 -30C-12.6 -36.8 -13 -37.6 -13 -37.6C-13 -37.6 -6.6 -30.4 -5 -30.4C-5 -30.4 8.2 -38 9.4 -13.6C9.4 -13.6 16.2 -28 7 -34.8C7 -34.8 -7.8 -36.8 -6.6 -42L0.6 -54.4C4.2 -59.6 2.6 -56.8 2.6 -56.8z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-17.8 -41.6C-17.8 -41.6 -30.6 -41.6 -33.8 -36.4L-41 -26.8C-41 -26.8 -23.8 -36.8 -19.8 -38C-15.8 -39.2 -17.8 -41.6 -17.8 -41.6z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-57.8 -35.2C-57.8 -35.2 -59.8 -34 -60.2 -31.2C-60.6 -28.4 -63 -28 -62.2 -25.2C-61.4 -22.4 -59.4 -20 -59.4 -24C-59.4 -28 -57.8 -30 -57 -31.2C-56.2 -32.4 -54.6 -36.8 -57.8 -35.2z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-66.6 26C-66.6 26 -75 22 -78.2 18.4C-81.4 14.8 -80.948 19.966 -85.8 19.6C-91.647 19.159 -90.6 3.2 -90.6 3.2L-94.6 10.8C-94.6 10.8 -95.8 25.2 -87.8 22.8C-83.893 21.628 -82.6 23.2 -84.2 24C-85.8 24.8 -78.6 25.2 -81.4 26.8C-84.2 28.4 -69.8 23.2 -72.2 33.6L-66.6 26z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-79.2 40.4C-79.2 40.4 -94.6 44.8 -98.2 35.2C-98.2 35.2 -103 37.6 -100.8 40.6C-98.6 43.6 -97.4 44 -97.4 44C-97.4 44 -92 45.2 -92.6 46C-93.2 46.8 -95.6 50.2 -95.6 50.2C-95.6 50.2 -85.4 44.2 -79.2 40.4z"}
++ ,
++ {"fill": "#ffffff",
++  "path":"M149.201 118.601C148.774 120.735 147.103 121.536 145.201 122.201C143.284 121.243 140.686 118.137 138.801 120.201C138.327 119.721 137.548 119.661 137.204 118.999C136.739 118.101 137.011 117.055 136.669 116.257C136.124 114.985 135.415 113.619 135.601 112.201C137.407 111.489 138.002 109.583 137.528 107.82C137.459 107.563 137.03 107.366 137.23 107.017C137.416 106.694 137.734 106.467 138.001 106.2C137.866 106.335 137.721 106.568 137.61 106.548C137 106.442 137.124 105.805 137.254 105.418C137.839 103.672 139.853 103.408 141.201 104.6C141.457 104.035 141.966 104.229 142.401 104.2C142.351 103.621 142.759 103.094 142.957 102.674C143.475 101.576 145.104 102.682 145.901 102.07C146.977 101.245 148.04 100.546 149.118 101.149C150.927 102.162 152.636 103.374 153.835 105.115C154.41 105.949 154.65 107.23 154.592 108.188C154.554 108.835 153.173 108.483 152.83 109.412C152.185 111.16 154.016 111.679 154.772 113.017C154.97 113.366 154.706 113.67 154.391 113.768C153.98 113.896 153.196 113.707 153.334 114.16C154.306 117.353 151.55 118.031 149.201 118.601z"}
++ ,
++ {"fill": "#ffffff",
++  "path":"M139.6 138.201C139.593 136.463 137.992 134.707 139.201 133.001C139.336 133.135 139.467 133.356 139.601 133.356C139.736 133.356 139.867 133.135 140.001 133.001C141.496 135.217 145.148 136.145 145.006 138.991C144.984 139.438 143.897 140.356 144.801 141.001C142.988 142.349 142.933 144.719 142.001 146.601C140.763 146.315 139.551 145.952 138.401 145.401C138.753 143.915 138.636 142.231 139.456 140.911C139.89 140.213 139.603 139.134 139.6 138.201z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-26.6 129.201C-26.6 129.201 -43.458 139.337 -29.4 124.001C-20.6 114.401 -10.6 108.801 -10.6 108.801C-10.6 108.801 -0.2 104.4 3.4 103.2C7 102 22.2 96.8 25.4 96.4C28.6 96 38.2 92 45 96C51.8 100 59.8 104.4 59.8 104.4C59.8 104.4 43.4 96 39.8 98.4C36.2 100.8 29 100.4 23 103.6C23 103.6 8.2 108.001 5 110.001C1.8 112.001 -8.6 123.601 -10.2 122.801C-11.8 122.001 -9.8 121.601 -8.6 118.801C-7.4 116.001 -9.4 114.401 -17.4 120.801C-25.4 127.201 -26.6 129.201 -26.6 129.201z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-19.195 123.234C-19.195 123.234 -17.785 110.194 -9.307 111.859C-9.307 111.859 -1.081 107.689 1.641 105.721C1.641 105.721 9.78 104.019 11.09 103.402C29.569 94.702 44.288 99.221 44.835 98.101C45.381 96.982 65.006 104.099 68.615 108.185C69.006 108.628 58.384 102.588 48.686 100.697C40.413 99.083 18.811 100.944 7.905 106.48C4.932 107.989 -4.013 113.773 -6.544 113.662C-9.075 113.55 -19.195 123.234 -19.195 123.234z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-23 148.801C-23 148.801 -38.2 146.401 -21.4 144.801C-21.4 144.801 -3.4 142.801 0.6 137.601C0.6 137.601 14.2 128.401 17 128.001C19.8 127.601 49.8 120.401 50.2 118.001C50.6 115.601 56.2 115.601 57.8 116.401C59.4 117.201 58.6 118.401 55.8 119.201C53 120.001 21.8 136.401 15.4 137.601C9 138.801 -2.6 146.401 -7.4 147.601C-12.2 148.801 -23 148.801 -23 148.801z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-3.48 141.403C-3.48 141.403 -12.062 140.574 -3.461 139.755C-3.461 139.755 5.355 136.331 7.403 133.668C7.403 133.668 14.367 128.957 15.8 128.753C17.234 128.548 31.194 124.861 31.399 123.633C31.604 122.404 65.67 109.823 70.09 113.013C73.001 115.114 63.1 113.437 53.466 117.847C52.111 118.467 18.258 133.054 14.981 133.668C11.704 134.283 5.765 138.174 3.307 138.788C0.85 139.403 -3.48 141.403 -3.48 141.403z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-11.4 143.601C-11.4 143.601 -6.2 143.201 -7.4 144.801C-8.6 146.401 -11 145.601 -11 145.601L-11.4 143.601z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-18.6 145.201C-18.6 145.201 -13.4 144.801 -14.6 146.401C-15.8 148.001 -18.2 147.201 -18.2 147.201L-18.6 145.201z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-29 146.801C-29 146.801 -23.8 146.401 -25 148.001C-26.2 149.601 -28.6 148.801 -28.6 148.801L-29 146.801z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-36.6 147.601C-36.6 147.601 -31.4 147.201 -32.6 148.801C-33.8 150.401 -36.2 149.601 -36.2 149.601L-36.6 147.601z"}
++ ,
++ {"fill": "#000000",
++  "path":"M1.8 108.001C1.8 108.001 6.2 108.001 5 109.601C3.8 111.201 0.6 110.801 0.6 110.801L1.8 108.001z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-8.2 113.601C-8.2 113.601 -1.694 111.46 -4.2 114.801C-5.4 116.401 -7.8 115.601 -7.8 115.601L-8.2 113.601z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-19.4 118.401C-19.4 118.401 -14.2 118.001 -15.4 119.601C-16.6 121.201 -19 120.401 -19 120.401L-19.4 118.401z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-27 124.401C-27 124.401 -21.8 124.001 -23 125.601C-24.2 127.201 -26.6 126.401 -26.6 126.401L-27 124.401z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-33.8 129.201C-33.8 129.201 -28.6 128.801 -29.8 130.401C-31 132.001 -33.4 131.201 -33.4 131.201L-33.8 129.201z"}
++ ,
++ {"fill": "#000000",
++  "path":"M5.282 135.598C5.282 135.598 12.203 135.066 10.606 137.195C9.009 139.325 5.814 138.26 5.814 138.26L5.282 135.598z"}
++ ,
++ {"fill": "#000000",
++  "path":"M15.682 130.798C15.682 130.798 22.603 130.266 21.006 132.395C19.409 134.525 16.214 133.46 16.214 133.46L15.682 130.798z"}
++ ,
++ {"fill": "#000000",
++  "path":"M26.482 126.398C26.482 126.398 33.403 125.866 31.806 127.995C30.209 130.125 27.014 129.06 27.014 129.06L26.482 126.398z"}
++ ,
++ {"fill": "#000000",
++  "path":"M36.882 121.598C36.882 121.598 43.803 121.066 42.206 123.195C40.609 125.325 37.414 124.26 37.414 124.26L36.882 121.598z"}
++ ,
++ {"fill": "#000000",
++  "path":"M9.282 103.598C9.282 103.598 16.203 103.066 14.606 105.195C13.009 107.325 9.014 107.06 9.014 107.06L9.282 103.598z"}
++ ,
++ {"fill": "#000000",
++  "path":"M19.282 100.398C19.282 100.398 26.203 99.866 24.606 101.995C23.009 104.125 18.614 103.86 18.614 103.86L19.282 100.398z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-3.4 140.401C-3.4 140.401 1.8 140.001 0.6 141.601C-0.6 143.201 -3 142.401 -3 142.401L-3.4 140.401z"}
++ ,
++ {"fill": "#992600",
++  "path":"M-76.6 41.2C-76.6 41.2 -81 50 -81.4 53.2C-81.4 53.2 -80.6 44.4 -79.4 42.4C-78.2 40.4 -76.6 41.2 -76.6 41.2z"}
++ ,
++ {"fill": "#992600",
++  "path":"M-95 55.2C-95 55.2 -98.2 69.6 -97.8 72.4C-97.8 72.4 -99 60.8 -98.6 59.6C-98.2 58.4 -95 55.2 -95 55.2z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-74.2 -19.4L-74.4 -16.2L-76.6 -16C-76.6 -16 -62.4 -3.4 -61.8 4.2C-61.8 4.2 -61 -4 -74.2 -19.4z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-70.216 -18.135C-70.647 -18.551 -70.428 -19.296 -70.836 -19.556C-71.645 -20.072 -69.538 -20.129 -69.766 -20.845C-70.149 -22.051 -69.962 -22.072 -70.084 -23.348C-70.141 -23.946 -69.553 -25.486 -69.168 -25.926C-67.722 -27.578 -69.046 -30.51 -67.406 -32.061C-67.102 -32.35 -66.726 -32.902 -66.441 -33.32C-65.782 -34.283 -64.598 -34.771 -63.648 -35.599C-63.33 -35.875 -63.531 -36.702 -62.962 -36.61C-62.248 -36.495 -61.007 -36.625 -61.052 -35.784C-61.165 -33.664 -62.494 -31.944 -63.774 -30.276C-63.323 -29.572 -63.781 -28.937 -64.065 -28.38C-65.4 -25.76 -65.211 -22.919 -65.385 -20.079C-65.39 -19.994 -65.697 -19.916 -65.689 -19.863C-65.336 -17.528 -64.752 -15.329 -63.873 -13.1C-63.507 -12.17 -63.036 -11.275 -62.886 -10.348C-62.775 -9.662 -62.672 -8.829 -63.08 -8.124C-61.045 -5.234 -62.354 -2.583 -61.185 0.948C-60.978 1.573 -59.286 3.487 -59.749 3.326C-62.262 2.455 -62.374 2.057 -62.551 1.304C-62.697 0.681 -63.027 -0.696 -63.264 -1.298C-63.328 -1.462 -63.499 -3.346 -63.577 -3.468C-65.09 -5.85 -63.732 -5.674 -65.102 -8.032C-66.53 -8.712 -67.496 -9.816 -68.619 -10.978C-68.817 -11.182 -67.674 -11.906 -67.855 -12.119C-68.947 -13.408 -70.1 -14.175 -69.764 -15.668C-69.609 -16.358 -69.472 -17.415 -70.216 -18.135z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-73.8 -16.4C-73.8 -16.4 -73.4 -9.6 -71 -8C-68.6 -6.4 -69.8 -7.2 -73 -8.4C-76.2 -9.6 -75 -10.4 -75 -10.4C-75 -10.4 -77.8 -10 -75.4 -8C-73 -6 -69.4 -3.6 -71 -3.6C-72.6 -3.6 -80.2 -7.6 -80.2 -10.4C-80.2 -13.2 -81.2 -17.3 -81.2 -17.3C-81.2 -17.3 -80.1 -18.1 -75.3 -18C-75.3 -18 -73.9 -17.3 -73.8 -16.4z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-74.6 2.2C-74.6 2.2 -83.12 -0.591 -101.6 2.8C-101.6 2.8 -92.569 0.722 -73.8 3C-63.5 4.25 -74.6 2.2 -74.6 2.2z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-72.502 2.129C-72.502 2.129 -80.748 -1.389 -99.453 0.392C-99.453 0.392 -90.275 -0.897 -71.774 2.995C-61.62 5.131 -72.502 2.129 -72.502 2.129z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-70.714 2.222C-70.714 2.222 -78.676 -1.899 -97.461 -1.514C-97.461 -1.514 -88.213 -2.118 -70.052 3.14C-60.086 6.025 -70.714 2.222 -70.714 2.222z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-69.444 2.445C-69.444 2.445 -76.268 -1.862 -93.142 -2.96C-93.142 -2.96 -84.803 -2.79 -68.922 3.319C-60.206 6.672 -69.444 2.445 -69.444 2.445z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M45.84 12.961C45.84 12.961 44.91 13.605 45.124 12.424C45.339 11.243 73.547 -1.927 77.161 -1.677C77.161 -1.677 46.913 11.529 45.84 12.961z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M42.446 13.6C42.446 13.6 41.57 14.315 41.691 13.121C41.812 11.927 68.899 -3.418 72.521 -3.452C72.521 -3.452 43.404 12.089 42.446 13.6z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M39.16 14.975C39.16 14.975 38.332 15.747 38.374 14.547C38.416 13.348 58.233 -2.149 68.045 -4.023C68.045 -4.023 50.015 4.104 39.16 14.975z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M36.284 16.838C36.284 16.838 35.539 17.532 35.577 16.453C35.615 15.373 53.449 1.426 62.28 -0.26C62.28 -0.26 46.054 7.054 36.284 16.838z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M4.6 164.801C4.6 164.801 -10.6 162.401 6.2 160.801C6.2 160.801 24.2 158.801 28.2 153.601C28.2 153.601 41.8 144.401 44.6 144.001C47.4 143.601 63.8 140.001 64.2 137.601C64.6 135.201 70.6 132.801 72.2 133.601C73.8 134.401 73.8 143.601 71 144.401C68.2 145.201 49.4 152.401 43 153.601C36.6 154.801 25 162.401 20.2 163.601C15.4 164.801 4.6 164.801 4.6 164.801z"}
++ ,
++ {"fill": "#000000",
++  "path":"M77.6 127.401C77.6 127.401 74.6 129.001 73.4 131.601C73.4 131.601 67 142.201 52.8 145.401C52.8 145.401 29.8 154.401 22 156.401C22 156.401 8.6 161.401 1.2 160.601C1.2 160.601 -5.8 160.801 0.4 162.401C0.4 162.401 20.6 160.401 24 158.601C24 158.601 39.6 153.401 42.6 150.801C45.6 148.201 63.8 143.201 66 141.201C68.2 139.201 78 130.801 77.6 127.401z"}
++ ,
++ {"fill": "#000000",
++  "path":"M18.882 158.911C18.882 158.911 24.111 158.685 22.958 160.234C21.805 161.784 19.357 160.91 19.357 160.91L18.882 158.911z"}
++ ,
++ {"fill": "#000000",
++  "path":"M11.68 160.263C11.68 160.263 16.908 160.037 15.756 161.586C14.603 163.136 12.155 162.263 12.155 162.263L11.68 160.263z"}
++ ,
++ {"fill": "#000000",
++  "path":"M1.251 161.511C1.251 161.511 6.48 161.284 5.327 162.834C4.174 164.383 1.726 163.51 1.726 163.51L1.251 161.511z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-6.383 162.055C-6.383 162.055 -1.154 161.829 -2.307 163.378C-3.46 164.928 -5.908 164.054 -5.908 164.054L-6.383 162.055z"}
++ ,
++ {"fill": "#000000",
++  "path":"M35.415 151.513C35.415 151.513 42.375 151.212 40.84 153.274C39.306 155.336 36.047 154.174 36.047 154.174L35.415 151.513z"}
++ ,
++ {"fill": "#000000",
++  "path":"M45.73 147.088C45.73 147.088 51.689 143.787 51.155 148.849C50.885 151.405 46.362 149.749 46.362 149.749L45.73 147.088z"}
++ ,
++ {"fill": "#000000",
++  "path":"M54.862 144.274C54.862 144.274 62.021 140.573 60.287 146.035C59.509 148.485 55.493 146.935 55.493 146.935L54.862 144.274z"}
++ ,
++ {"fill": "#000000",
++  "path":"M64.376 139.449C64.376 139.449 68.735 134.548 69.801 141.21C70.207 143.748 65.008 142.11 65.008 142.11L64.376 139.449z"}
++ ,
++ {"fill": "#000000",
++  "path":"M26.834 155.997C26.834 155.997 32.062 155.77 30.91 157.32C29.757 158.869 27.308 157.996 27.308 157.996L26.834 155.997z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M62.434 34.603C62.434 34.603 61.708 35.268 61.707 34.197C61.707 33.127 79.191 19.863 88.034 18.479C88.034 18.479 71.935 25.208 62.434 34.603z"}
++ ,
++ {"fill": "#000000",
++  "path":"M65.4 98.4C65.4 98.4 87.401 120.801 96.601 124.401C96.601 124.401 105.801 135.601 101.801 161.601C101.801 161.601 98.601 169.201 95.401 148.401C95.401 148.401 98.601 123.201 87.401 139.201C87.401 139.201 79 129.301 85.4 129.601C85.4 129.601 88.601 131.601 89.001 130.001C89.401 128.401 81.4 114.801 64.2 100.4C47 86 65.4 98.4 65.4 98.4z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M7 137.201C7 137.201 6.8 135.401 8.6 136.201C10.4 137.001 104.601 143.201 136.201 167.201C136.201 167.201 91.001 144.001 7 137.201z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M17.4 132.801C17.4 132.801 17.2 131.001 19 131.801C20.8 132.601 157.401 131.601 181.001 164.001C181.001 164.001 159.001 138.801 17.4 132.801z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M29 128.801C29 128.801 28.8 127.001 30.6 127.801C32.4 128.601 205.801 115.601 229.401 148.001C229.401 148.001 219.801 122.401 29 128.801z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M39 124.001C39 124.001 38.8 122.201 40.6 123.001C42.4 123.801 164.601 85.2 188.201 117.601C188.201 117.601 174.801 93 39 124.001z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-19 146.801C-19 146.801 -19.2 145.001 -17.4 145.801C-15.6 146.601 2.2 148.801 4.2 187.601C4.2 187.601 -3 145.601 -19 146.801z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-27.8 148.401C-27.8 148.401 -28 146.601 -26.2 147.401C-24.4 148.201 -10.2 143.601 -13 182.401C-13 182.401 -11.8 147.201 -27.8 148.401z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-35.8 148.801C-35.8 148.801 -36 147.001 -34.2 147.801C-32.4 148.601 -17 149.201 -29.4 171.601C-29.4 171.601 -19.8 147.601 -35.8 148.801z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M11.526 104.465C11.526 104.465 11.082 106.464 12.631 105.247C28.699 92.622 61.141 33.72 116.826 28.086C116.826 28.086 78.518 15.976 11.526 104.465z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M22.726 102.665C22.726 102.665 21.363 101.472 23.231 100.847C25.099 100.222 137.541 27.72 176.826 35.686C176.826 35.686 149.719 28.176 22.726 102.665z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M1.885 108.767C1.885 108.767 1.376 110.366 3.087 109.39C12.062 104.27 15.677 47.059 59.254 45.804C59.254 45.804 26.843 31.09 1.885 108.767z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-18.038 119.793C-18.038 119.793 -19.115 121.079 -17.162 120.825C-6.916 119.493 14.489 78.222 58.928 83.301C58.928 83.301 26.962 68.955 -18.038 119.793z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-6.8 113.667C-6.8 113.667 -7.611 115.136 -5.742 114.511C4.057 111.237 17.141 66.625 61.729 63.078C61.729 63.078 27.603 55.135 -6.8 113.667z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-25.078 124.912C-25.078 124.912 -25.951 125.954 -24.369 125.748C-16.07 124.669 1.268 91.24 37.264 95.354C37.264 95.354 11.371 83.734 -25.078 124.912z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-32.677 130.821C-32.677 130.821 -33.682 131.866 -32.091 131.748C-27.923 131.439 2.715 98.36 21.183 113.862C21.183 113.862 9.168 95.139 -32.677 130.821z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M36.855 98.898C36.855 98.898 35.654 97.543 37.586 97.158C39.518 96.774 160.221 39.061 198.184 51.927C198.184 51.927 172.243 41.053 36.855 98.898z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M3.4 163.201C3.4 163.201 3.2 161.401 5 162.201C6.8 163.001 22.2 163.601 9.8 186.001C9.8 186.001 19.4 162.001 3.4 163.201z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M13.8 161.601C13.8 161.601 13.6 159.801 15.4 160.601C17.2 161.401 35 163.601 37 202.401C37 202.401 29.8 160.401 13.8 161.601z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M20.6 160.001C20.6 160.001 20.4 158.201 22.2 159.001C24 159.801 48.6 163.201 72.2 195.601C72.2 195.601 36.6 158.801 20.6 160.001z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M28.225 157.972C28.225 157.972 27.788 156.214 29.678 156.768C31.568 157.322 52.002 155.423 90.099 189.599C90.099 189.599 43.924 154.656 28.225 157.972z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M38.625 153.572C38.625 153.572 38.188 151.814 40.078 152.368C41.968 152.922 76.802 157.423 128.499 192.399C128.499 192.399 54.324 150.256 38.625 153.572z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-1.8 142.001C-1.8 142.001 -2 140.201 -0.2 141.001C1.6 141.801 55 144.401 85.4 171.201C85.4 171.201 50.499 146.426 -1.8 142.001z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M-11.8 146.001C-11.8 146.001 -12 144.201 -10.2 145.001C-8.4 145.801 16.2 149.201 39.8 181.601C39.8 181.601 4.2 144.801 -11.8 146.001z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M49.503 148.962C49.503 148.962 48.938 147.241 50.864 147.655C52.79 148.068 87.86 150.004 141.981 181.098C141.981 181.098 64.317 146.704 49.503 148.962z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M57.903 146.562C57.903 146.562 57.338 144.841 59.264 145.255C61.19 145.668 96.26 147.604 150.381 178.698C150.381 178.698 73.317 143.904 57.903 146.562z"}
++ ,
++ {"fill": "#ffffff", "stroke":"#000000", "width":0.1,
++  "path":"M67.503 141.562C67.503 141.562 66.938 139.841 68.864 140.255C70.79 140.668 113.86 145.004 203.582 179.298C203.582 179.298 82.917 138.904 67.503 141.562z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-43.8 148.401C-43.8 148.401 -38.6 148.001 -39.8 149.601C-41 151.201 -43.4 150.401 -43.4 150.401L-43.8 148.401z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-13 162.401C-13 162.401 -7.8 162.001 -9 163.601C-10.2 165.201 -12.6 164.401 -12.6 164.401L-13 162.401z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-21.8 162.001C-21.8 162.001 -16.6 161.601 -17.8 163.201C-19 164.801 -21.4 164.001 -21.4 164.001L-21.8 162.001z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-117.169 150.182C-117.169 150.182 -112.124 151.505 -113.782 152.624C-115.439 153.744 -117.446 152.202 -117.446 152.202L-117.169 150.182z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-115.169 140.582C-115.169 140.582 -110.124 141.905 -111.782 143.024C-113.439 144.144 -115.446 142.602 -115.446 142.602L-115.169 140.582z"}
++ ,
++ {"fill": "#000000",
++  "path":"M-122.369 136.182C-122.369 136.182 -117.324 137.505 -118.982 138.624C-120.639 139.744 -122.646 138.202 -122.646 138.202L-122.369 136.182z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-42.6 211.201C-42.6 211.201 -44.2 211.201 -48.2 213.201C-50.2 213.201 -61.4 216.801 -67 226.801C-67 226.801 -54.6 217.201 -42.6 211.201z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M45.116 303.847C45.257 304.105 45.312 304.525 45.604 304.542C46.262 304.582 47.495 304.883 47.37 304.247C46.522 299.941 45.648 295.004 41.515 293.197C40.876 292.918 39.434 293.331 39.36 294.215C39.233 295.739 39.116 297.088 39.425 298.554C39.725 299.975 41.883 299.985 42.8 298.601C43.736 300.273 44.168 302.116 45.116 303.847z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M34.038 308.581C34.786 309.994 34.659 311.853 36.074 312.416C36.814 312.71 38.664 311.735 38.246 310.661C37.444 308.6 37.056 306.361 35.667 304.55C35.467 304.288 35.707 303.755 35.547 303.427C34.953 302.207 33.808 301.472 32.4 301.801C31.285 304.004 32.433 306.133 33.955 307.842C34.091 307.994 33.925 308.37 34.038 308.581z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-5.564 303.391C-5.672 303.014 -5.71 302.551 -5.545 302.23C-5.014 301.197 -4.221 300.075 -4.558 299.053C-4.906 297.997 -6.022 298.179 -6.672 298.748C-7.807 299.742 -7.856 301.568 -8.547 302.927C-8.743 303.313 -8.692 303.886 -9.133 304.277C-9.607 304.698 -10.047 306.222 -9.951 306.793C-9.898 307.106 -10.081 317.014 -9.859 316.751C-9.24 316.018 -6.19 306.284 -6.121 305.392C-6.064 304.661 -5.332 304.196 -5.564 303.391z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-31.202 296.599C-28.568 294.1 -25.778 291.139 -26.22 287.427C-26.336 286.451 -28.111 286.978 -28.298 287.824C-29.1 291.449 -31.139 294.11 -33.707 296.502C-35.903 298.549 -37.765 304.893 -38 305.401C-34.303 300.145 -32.046 297.399 -31.202 296.599z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-44.776 290.635C-44.253 290.265 -44.555 289.774 -44.338 289.442C-43.385 287.984 -42.084 286.738 -42.066 285C-42.063 284.723 -42.441 284.414 -42.776 284.638C-43.053 284.822 -43.395 284.952 -43.503 285.082C-45.533 287.531 -46.933 290.202 -48.376 293.014C-48.559 293.371 -49.703 297.862 -49.39 297.973C-49.151 298.058 -47.431 293.877 -47.221 293.763C-45.958 293.077 -45.946 291.462 -44.776 290.635z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-28.043 310.179C-27.599 309.31 -26.023 308.108 -26.136 307.219C-26.254 306.291 -25.786 304.848 -26.698 305.536C-27.955 306.484 -31.404 307.833 -31.674 313.641C-31.7 314.212 -28.726 311.519 -28.043 310.179z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-13.6 293.001C-13.2 292.333 -12.492 292.806 -12.033 292.543C-11.385 292.171 -10.774 291.613 -10.482 290.964C-9.512 288.815 -7.743 286.995 -7.6 284.601C-9.091 283.196 -9.77 285.236 -10.4 286.201C-11.723 284.554 -12.722 286.428 -14.022 286.947C-14.092 286.975 -14.305 286.628 -14.38 286.655C-15.557 287.095 -16.237 288.176 -17.235 288.957C-17.406 289.091 -17.811 288.911 -17.958 289.047C-18.61 289.65 -19.583 289.975 -19.863 290.657C-20.973 293.364 -24.113 295.459 -26 303.001C-25.619 303.91 -21.488 296.359 -21.001 295.661C-20.165 294.465 -20.047 297.322 -18.771 296.656C-18.72 296.629 -18.534 296.867 -18.4 297.001C-18.206 296.721 -17.988 296.492 -17.6 296.601C-17.6 296.201 -17.734 295.645 -17.533 295.486C-16.296 294.509 -16.38 293.441 -15.6 292.201C-15.142 292.99 -14.081 292.271 -13.6 293.001z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M46.2 347.401C46.2 347.401 53.6 327.001 49.2 315.801C49.2 315.801 60.6 337.401 56 348.601C56 348.601 55.6 338.201 51.6 333.201C51.6 333.201 47.6 346.001 46.2 347.401z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M31.4 344.801C31.4 344.801 36.8 336.001 28.8 317.601C28.8 317.601 28 338.001 21.2 349.001C21.2 349.001 35.4 328.801 31.4 344.801z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M21.4 342.801C21.4 342.801 21.2 322.801 21.6 319.801C21.6 319.801 17.8 336.401 7.6 346.001C7.6 346.001 22 334.001 21.4 342.801z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M11.8 310.801C11.8 310.801 17.8 324.401 7.8 342.801C7.8 342.801 14.2 330.601 9.4 323.601C9.4 323.601 12 320.201 11.8 310.801z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-7.4 342.401C-7.4 342.401 -8.4 326.801 -6.6 324.601C-6.6 324.601 -6.4 318.201 -6.8 317.201C-6.8 317.201 -2.8 311.001 -2.6 318.401C-2.6 318.401 -1.2 326.201 1.6 330.801C1.6 330.801 5.2 336.201 5 342.601C5 342.601 -5 312.401 -7.4 342.401z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-11 314.801C-11 314.801 -17.6 325.601 -19.4 344.601C-19.4 344.601 -20.8 338.401 -17 324.001C-17 324.001 -12.8 308.601 -11 314.801z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-32.8 334.601C-32.8 334.601 -27.8 329.201 -26.4 324.201C-26.4 324.201 -22.8 308.401 -29.2 317.001C-29.2 317.001 -29 325.001 -37.2 332.401C-37.2 332.401 -32.4 330.001 -32.8 334.601z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-38.6 329.601C-38.6 329.601 -35.2 312.201 -34.4 311.401C-34.4 311.401 -32.6 308.001 -35.4 311.201C-35.4 311.201 -44.2 330.401 -48.2 337.001C-48.2 337.001 -40.2 327.801 -38.6 329.601z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-44.4 313.001C-44.4 313.001 -32.8 290.601 -54.6 316.401C-54.6 316.401 -43.6 306.601 -44.4 313.001z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M-59.8 298.401C-59.8 298.401 -55 279.601 -52.4 279.801C-52.4 279.801 -44.2 270.801 -50.8 281.401C-50.8 281.401 -56.8 291.001 -56.2 300.801C-56.2 300.801 -56.8 291.201 -59.8 298.401z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M270.5 287C270.5 287 258.5 277 256 273.5C256 273.5 269.5 292 269.5 299C269.5 299 272 291.5 270.5 287z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M276 265C276 265 255 250 251.5 242.5C251.5 242.5 278 272 278 276.5C278 276.5 278.5 267.5 276 265z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M293 111C293 111 281 103 279.5 105C279.5 105 290 111.5 292.5 120C292.5 120 291 111 293 111z"}
++ ,
++ {"fill": "#cccccc",
++  "path":"M301.5 191.5L284 179.5C284 179.5 303 196.5 303.5 200.5L301.5 191.5z"}
++ ,
++ {"stroke":"#000000",
++  "path":"M-89.25 169L-67.25 173.75"}
++ ,
++ {"stroke":"#000000",
++  "path":"M-39 331C-39 331 -39.5 327.5 -48.5 338"}
++ ,
++ {"stroke":"#000000",
++  "path":"M-33.5 336C-33.5 336 -31.5 329.5 -38 334"}
++ ,
++ {"stroke":"#000000",
++  "path":"M20.5 344.5C20.5 344.5 22 333.5 10.5 346.5"}
++];
index 0000000,0000000..2eb1bb2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,129 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "../contents"
++import "tiger.js" as Tiger
++Item {
++  id:container
++  width:360
++  height:600
++
++  Column {
++    spacing:5
++    anchors.fill:parent
++    Text { font.pointSize:25; text:"Tiger with SVG path"; anchors.horizontalCenter:parent.horizontalCenter}
++
++    Canvas {
++        id:canvas
++        width:360
++        height:360
++        smooth:true
++        renderTarget:Canvas.FramebufferObject
++        renderStrategy: Canvas.Cooperative
++        property string strokeStyle:"steelblue"
++        property string fillStyle:"yellow"
++        property bool fill:true
++        property bool stroke:true
++        property real alpha:alphaCtrl.value
++        property real scaleX : scaleXCtrl.value
++        property real scaleY : scaleYCtrl.value
++        property real rotate : rotateCtrl.value
++        property int frame:0
++
++        onFillChanged: requestPaint();
++        onStrokeChanged: requestPaint();
++        onAlphaChanged: requestPaint();
++        onScaleXChanged: requestPaint();
++        onScaleYChanged: requestPaint();
++        onRotateChanged: requestPaint();
++
++        onPainted : {
++            canvas.frame++;
++            if (canvas.frame < Tiger.tiger.length)
++                requestPaint();
++        }
++        onPaint: {
++            var ctx = canvas.getContext('2d');
++            ctx.save();
++            ctx.clearRect(0, 0, canvas.width, canvas.height);
++            ctx.globalAlpha = canvas.alpha;
++            ctx.scale(canvas.scaleX, canvas.scaleY);
++            ctx.rotate(canvas.rotate);
++            ctx.globalCompositeOperation = "source-over";
++            ctx.translate(canvas.width/2, canvas.height/2);
++            ctx.strokeStyle = Qt.rgba(.3, .3, .3,1);
++            ctx.lineWidth = 1;
++
++
++            for (var i = 0; i < canvas.frame && i < Tiger.tiger.length; i++) {
++            if (Tiger.tiger[i].width != undefined)
++            ctx.lineWidth = Tiger.tiger[i].width;
++
++            if (Tiger.tiger[i].path != undefined)
++            ctx.path = Tiger.tiger[i].path;
++
++            if (Tiger.tiger[i].fill != undefined) {
++            ctx.fillStyle = Tiger.tiger[i].fill;
++            ctx.fill();
++            }
++
++            if (Tiger.tiger[i].stroke != undefined) {
++            ctx.strokeStyle = Tiger.tiger[i].stroke;
++            ctx.stroke();
++            }
++        }
++            ctx.restore();
++    }
++    }
++    Rectangle {
++        id:controls
++        width:360
++        height:160
++        Column {
++          spacing:3
++          Slider {id:scaleXCtrl; width:300; height:30; min:0.1; max:10; init:0.5; name:"ScaleX"}
++          Slider {id:scaleYCtrl; width:300; height:30; min:0.1; max:10; init:0.5; name:"ScaleY"}
++          Slider {id:rotateCtrl; width:300; height:30; min:0; max:Math.PI*2; init:0; name:"Rotate"}
++          Slider {id:alphaCtrl; width:300; height:30; min:0; max:1; init:1; name:"Alpha"}
++        }
++    }
++  }
++}
index 0000000,0000000..8b90621
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,294 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id:twitterUser
++    property variant friends : [];
++    property string name : "";
++    property string twitterId : "";
++    property string image : "";
++    property string url : "";
++    property string desc : "";
++    width : 0;
++    height : 0;
++    property int posX:0;
++    property int posY:0;
++    property bool hasFocus : false;
++    property variant canvas;
++    property variant manager;
++    property variant linkColor;
++    property bool selected : false;
++
++    Rectangle {
++        id:twitterStatus
++        x:twitterUser.width
++        y:twitterUser.height
++        width:250
++        height:60
++        opacity: 0
++        border.color:"steelblue"
++        border.width:3
++        Column {
++            spacing:2
++            Text {color:"steelblue"; font.pointSize:15; width:250; height:30; text:twitterUser.name; wrapMode: Text.WrapAnywhere}
++            Text {color:"steelblue"; font.pointSize:8; width:250; height:30;  text:twitterUser.url; wrapMode: Text.WrapAnywhere}
++        }
++    }
++
++    function moved() {
++        twitterUser.posX = twitterUser.x;
++        twitterUser.posY = twitterUser.y;
++        twitterUser.canvas.requestPaint();
++    }
++
++    onXChanged: moved();
++    onYChanged: moved();
++
++    MouseArea {
++        anchors.fill:parent
++        drag.target : twitterUser
++        drag.axis : Drag.XandYAxis
++
++        onClicked: {
++            if (!twitterUser.selected) {
++                twitterUser.selected = true;
++                twitterStatus.opacity = 1;
++                twitterStatus.visible = true;
++            } else {
++                twitterUser.selected = false;
++                twitterStatus.opacity = 0;
++            }
++        }
++
++        onDoubleClicked : {
++            twitterStatus.opacity = 0;
++            twitterUser.selected = false;
++            twitterUser.hasFocus = true;
++            twitterUser.canvas.twitterName = twitterUser.name;
++            twitterUser.canvas.twitterId = twitterUser.twitterId;
++            twitterUser.canvas.loading = true;
++            twitterUser.createFriends();
++        }
++    }
++
++    function show(ctx, layoutChanged) {
++      var w = canvas.width;
++      var h = canvas.height;
++      if (twitterUser.hasFocus) {
++          twitterUser.width = 60
++          twitterUser.height = 60
++          twitterUser.posX = w/2;
++          twitterUser.posY = h/2;
++       } else {
++          twitterUser.width = 40
++          twitterUser.height = 40
++      }
++
++
++      if (twitterUser.hasFocus) {
++          if (layoutChanged)
++              twitterUser.layoutFriends();
++          twitterUser.linkFriends(ctx);
++          twitterUser.showFriends(ctx);
++          ctx.shadowOffsetX = 5;
++          ctx.shadowOffsetY = 5;
++          ctx.shadowBlur = 7;
++          ctx.shadowColor = "blue";
++          ctx.globalAlpha = 1;
++      }  else {
++          ctx.shadowOffsetX = 5;
++          ctx.shadowOffsetY = 5;
++          ctx.shadowBlur = 7;
++          ctx.shadowColor = twitterUser.linkColor;
++          ctx.globalAlpha = 0.6;
++      }
++
++      if (twitterUser.canvas.isImageLoaded(twitterUser.image)) {
++        ctx.drawImage(twitterUser.image, twitterUser.posX, twitterUser.posY, twitterUser.width, twitterUser.height);
++      }
++//      ctx.font = "15px";
++//      var nameSize = ctx.measureText(twitterUser.name).width;
++//      ctx.fillText(twitterUser.name, twitterUser.posX + nameSize/2 - twitterUser.width/2, twitterUser.posY + twitterUser.height/2 + 10);
++    }
++    function dump() {
++        console.log("name:" + twitterUser.name
++                  + " x:" + twitterUser.posX
++                  + " y:" + twitterUser.posY
++                  + " width:" + twitterUser.width
++                  + " height:" + twitterUser.height
++                  + " id:" + twitterUser.twitterId
++                  + " image:" + twitterUser.image
++                  + " url:" + twitterUser.url + "\n" + twitterUser.desc);
++    }
++
++    function layoutFriends() {
++        var w = canvas.width;
++        var h = canvas.height;
++        for (var i=0; i < twitterUser.friends.length; i++) {
++            var friend = manager.getById(twitterUser.friends[i]);
++            if (friend) {
++                friend.x = Math.random() *w;
++                friend.y = Math.random() *h;
++            }
++        }
++    }
++
++    function showFriends(ctx) {
++        var w = canvas.width;
++        var h = canvas.height;
++        for (var i=0; i < twitterUser.friends.length && i < 15; i++) {
++            var friend = manager.getById(twitterUser.friends[i]);
++            if (friend && twitterUser.canvas.isImageLoaded(friend.image)) {
++                friend.hasFocus = false;
++                friend.show(ctx, false);
++            }
++        }
++    }
++
++    function linkFriends(ctx) {
++        var w = canvas.width;
++        var h = canvas.height;
++        for (var i=0; i < twitterUser.friends.length && i < 15; i++) {
++            var friend = manager.getById(twitterUser.friends[i]);
++            if (friend && twitterUser.canvas.isImageLoaded(friend.image)) {
++                if (!friend.linkColor)
++                     friend.linkColor = Qt.rgba( ((Math.random() * 200) +55)/255
++                                               , ((Math.random() * 200) +55)/255
++                                               , ((Math.random() * 200) +55)/255, 0.8);
++                ctx.strokeStyle  = friend.linkColor;
++                ctx.lineWidth = 8;
++                ctx.beginPath();
++                ctx.moveTo(twitterUser.posX + twitterUser.width/2, twitterUser.posY + twitterUser.height/2);
++                ctx.lineTo(friend.x + friend.width/2, friend.y + friend.height/2);
++                ctx.stroke();
++            }
++        }
++    }
++
++
++    function create(url) {
++        var x = new XMLHttpRequest;
++        x.open("GET", url);
++
++        x.onreadystatechange = function() {
++            if (x.readyState == XMLHttpRequest.DONE) {
++                var user = eval('(' + x.responseText +')')[0];
++                twitterUser.name = user.name;
++                twitterUser.twitterId = user.id;
++                twitterUser.image = user.profile_image_url;
++                twitterUser.canvas.loadImage(twitterUser.image);
++                twitterUser.url = user.url;
++                twitterUser.desc = user.description;
++                twitterUser.createFriends();
++           }
++        }
++        x.send();
++    }
++
++    function createByName(name) {
++      if (twitterUser.name === "" && twitterUser.twitterId === "") {
++         twitterUser.name = name;
++         var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&screen_name=" + name;
++         twitterUser.create(userUrl);
++      }
++    }
++
++    function createById(id) {
++      if (twitterUser.name === "" && twitterUser.twitterId === "") {
++         twitterUser.twitterId = id;
++         var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id=" + id;
++         twitterUser.create(userUrl);
++      }
++    }
++
++    function createFriends() {
++      if (twitterUser.friends.length === 0) {
++          var x = new XMLHttpRequest;
++          var friendsUrl = "https://api.twitter.com/1/friends/ids.json?cursor=-1&stringify_ids=true&user_id=" + twitterUser.twitterId;
++          x.open("GET", friendsUrl);
++
++          x.onreadystatechange = function() {
++              if (x.readyState == XMLHttpRequest.DONE) {
++                 twitterUser.friends = eval('(' + x.responseText +')').ids;
++                 var doRequest = false;
++                  var userUrl = "http://api.twitter.com/1/users/lookup.json?stringify_ids=true&user_id=";
++
++                 for (var i=0; i<twitterUser.friends.length && i < 100; i++) {
++                    var friend = manager.getById(twitterUser.friends[i]);
++                    if (!friend) {
++                       userUrl += "," + twitterUser.friends[i];
++                       doRequest = true;
++                    }
++                 }
++
++                 if (!doRequest) return;
++
++                 var xx = new XMLHttpRequest;
++                 xx.open("GET", userUrl);
++                 xx.onreadystatechange = function() {
++                    if (xx.readyState == XMLHttpRequest.DONE) {
++                       var friendUsers = eval('(' + xx.responseText +')');
++                       for(var i=0; i<friendUsers.length; i++) {
++                           var friend = manager.createTwitterUser(twitterUser.canvas);
++                          friend.name = friendUsers[i].name;
++                          friend.twitterId = friendUsers[i].id;
++                          friend.image = friendUsers[i].profile_image_url ? friendUsers[i].profile_image_url : "";
++                          friend.url = friendUsers[i].url ? friendUsers[i].url : "";
++                          friend.desc = friendUsers[i].description ? friendUsers[i].description : "";
++                          friend.manager = twitterUser.manager;
++                          twitterUser.canvas.loadImage(friend.image);
++                       }
++
++                       if (twitterUser.hasFocus && twitterUser.canvas) {
++                           twitterUser.canvas.layoutChanged = true;
++                           twitterUser.canvas.loading = false;
++                           twitterUser.canvas.requestPaint();
++                       }
++                    }
++                 }
++                 xx.send();
++              }
++          }
++          x.send();
++      }
++    }
++}
index 0000000,0000000..6c8a1cd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,42 @@@
++var UserCache = function() {
++  this._users = [];
++}
++
++
++UserCache.prototype.getById = function(id){
++  for (var i=0; i < this._users.length; i++){
++    var user = this._users[i];
++    if (user.twitterId == id) {
++      return user;
++    }
++  }
++}
++UserCache.prototype.getByName = function(name){
++  for (var i=0; i < this._users.length; i++){
++    var user = this._users[i];
++    if (user.name == name)
++        return user;
++  }
++}
++
++UserCache.prototype.add = function(user){
++  this._users[this._users.length] = user;
++}
++
++
++var cache = new UserCache;
++
++function getById(id) {
++    return cache.getById(id);
++}
++
++function getByName(name) {
++    return cache.getByName(name);
++}
++
++function createTwitterUser(canvas) {
++    var user = Qt.createQmlObject("import QtQuick 2.0; TwitterUser{}", canvas);
++    user.canvas = canvas;
++    cache.add(user);
++    return user;
++}
index 0000000,0000000..9dc2bcc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,141 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "../contents"
++import "cache.js" as TwitterUserCache
++Rectangle {
++    width:360
++    height:600
++    color:"black"
++    QtObject {
++        id:twitterManager
++        function getById(id) {
++            return TwitterUserCache.cache.getById(id);
++        }
++
++        function getByName(name) {
++            return TwitterUserCache.cache.getByName(name);
++        }
++
++        function createTwitterUser(canvas) {
++            return TwitterUserCache.createTwitterUser(canvas);
++        }
++    }
++    Rectangle {
++        id:inputContainer
++        width:parent.width-4
++        height:40
++        anchors.top:parent.top
++        anchors.topMargin:4
++        anchors.horizontalCenter:parent.horizontalCenter
++        radius:8
++        border.color:"steelblue"
++        Text {
++            text:inputName.text == "" ? "Enter your twitter name..." : ""
++            id:inputLabel
++            anchors.centerIn:parent
++            font.pointSize:12
++            opacity:.5
++            color:"steelblue"
++        }
++        TextInput {
++            id:inputName
++            anchors.centerIn:parent
++            font.pointSize : 20
++            opacity:1
++            color:"steelblue"
++            width:parent.width-6
++            height:parent.height-6
++            text:""
++            autoScroll:true
++            focus:true
++            selectByMouse:true
++            onAccepted : {canvas.twitterName = text; canvas.requestPaint();}
++        }
++    }
++    Canvas {
++      id:canvas
++      width:parent.width
++      anchors.top :inputContainer.bottom
++      anchors.bottom : parent.bottom
++      smooth:true
++      renderTarget:Canvas.Image
++      renderStrategy: Canvas.Immediate
++
++      property bool layoutChanged:true
++      property string twitterName:""
++      property string twitterId:""
++      property bool loading:false
++
++      onLoadingChanged: requestPaint();
++      onWidthChanged: { layoutChanged = true; requestPaint();}
++      onHeightChanged:  { layoutChanged = true; requestPaint();}
++      onTwitterNameChanged: inputName.text = twitterName;
++      onImageLoaded:requestPaint();
++      onPaint: {
++      var ctx = canvas.getContext('2d');
++      ctx.save();
++      ctx.fillStyle="black";
++      ctx.fillRect(0, 0, canvas.width, canvas.height);
++
++      if (canvas.twitterName != "" || canvas.twitterId != "") {
++          var user = canvas.twitterId ? TwitterUserCache.getById(canvas.twitterId) : TwitterUserCache.getByName(canvas.twitterName);
++          if (!user) {
++              user = TwitterUserCache.createTwitterUser(canvas);
++              user.hasFocus = true;
++              user.manager = twitterManager;
++              user.createByName(canvas.twitterName);
++              canvas.loading = true;
++          }
++
++          if (canvas.loading) {
++              ctx.font = "40px";
++              ctx.fillStyle = "steelblue";
++              ctx.fillText("Loading...", canvas.width/2 - 80, canvas.height/2);
++          } else {
++              user.show(ctx, layoutChanged);
++          }
++          layoutChanged = false;
++      }
++      ctx.restore();
++    }
++  }
++}
index 0000000,0000000..3f53531
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++TEMPLATE = app
++
++QT += quick qml
++SOURCES += main.cpp
++
++target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/draganddrop
++qml.files = draganddrop.qml tiles views
++qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/draganddrop
++INSTALLS += target qml
++
index 0000000,0d74fbf..0d74fbf
mode 000000,100644..100644
--- /dev/null
index 0000000,0000000..a084bf0
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..fcc6b47
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,60 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++import QtQuick 2.0
++
++Item {
++    property alias mode: image.fillMode
++    property alias caption: captionItem.text
++
++    width: parent.cellWidth; height: parent.cellHeight
++
++    Image {
++        id: image
++        width: parent.width; height: parent.height - captionItem.height
++        source: "qt-logo.png"
++        clip: true      // only makes a difference if mode is PreserveAspectCrop
++        smooth: true
++    }
++
++    Text { 
++        id: captionItem
++        anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom
++    }
++}
index 0000000,0000000..e6fd13b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,54 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    property alias color : rectangle.color
++
++    BorderImage {
++        anchors.fill: rectangle
++        anchors { leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8 }
++        border { left: 10; top: 10; right: 10; bottom: 10 }
++        source: "shadow.png"; smooth: true
++    }
++
++    Rectangle { id: rectangle; anchors.fill: parent }
++}
index 0000000,0000000..486eaae
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..506f6f5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,7 @@@
++border.left:30
++border.top:30
++border.right:30
++border.bottom:30
++horizontalTileRule:Round
++verticalTileRule:Round
++source:colors.png
index 0000000,0000000..e4989a7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++border.left:30
++border.top:30
++border.right:30
++border.bottom:30
++source:colors.png
index 0000000,dfb62f3..dfb62f3
mode 000000,100644..100644
Binary files differ
index 0000000,0000000..14ddf2a
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..431af85
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..fb0e857
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..89abac6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++TEMPLATE = app
++
++QT += quick qml
++SOURCES += main.cpp
++
++target.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/imageelements
++qml.files = borderimage.qml content imageelements.qml image.qml shadows.qml simplesprite.qml spriteimage.qml
++qml.path = $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qtquick/imageelements
++INSTALLS += target qml
++
index 0000000,0000000..4292a0c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++import QmlProject 1.1
++
++Project {
++    mainFile: "imageelements.qml"
++
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..aa5022a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,64 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "content"
++
++Rectangle {
++    id: window
++
++    width: 480; height: 320
++    color: "gray"
++
++    ShadowRectangle {
++        anchors.centerIn: parent; width: 250; height: 250
++        color: "lightsteelblue"
++    }
++
++    ShadowRectangle {
++        anchors.centerIn: parent; width: 200; height: 200
++        color: "steelblue"
++    }
++
++    ShadowRectangle {
++        anchors.centerIn: parent; width: 150; height: 150
++        color: "thistle"
++    }
++}
index 0000000,0000000..dc68aa2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,65 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++FocusScope {
++    id: container
++
++    property bool open: false
++
++    Item {
++        anchors.fill: parent
++
++        Rectangle {
++            anchors.fill: parent
++            color: "#D1DBBD"
++            focus: true
++            Keys.onRightPressed: mainView.focus = true
++
++            Text { 
++                anchors { top: parent.top; horizontalCenter: parent.horizontalCenter; margins: 30 }
++                color: "black"
++                font.pixelSize: 14
++                text: "Context Menu"
++            }
++        }
++    }
++}
index 0000000,0000000..75bbe68
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,105 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++FocusScope {
++    property alias interactive: gridView.interactive
++
++    onActiveFocusChanged: {
++        if (activeFocus) 
++            mainView.state = ""
++    }
++
++    Rectangle {
++        anchors.fill: parent
++        clip: true
++        gradient: Gradient {
++            GradientStop { position: 0.0; color: "#193441" }
++            GradientStop { position: 1.0; color: Qt.darker("#193441") }
++        }
++
++        GridView {
++            id: gridView
++            anchors.fill: parent; anchors.leftMargin: 20; anchors.rightMargin: 20
++            cellWidth: 152; cellHeight: 152
++            focus: true
++            model: 12
++
++            KeyNavigation.down: listMenu
++            KeyNavigation.left: contextMenu
++
++            delegate: Item {
++                id: container
++                width: GridView.view.cellWidth; height: GridView.view.cellHeight
++
++                Rectangle {
++                    id: content
++                    color: "transparent"
++                    smooth: true
++                    anchors.fill: parent; anchors.margins: 20; radius: 10
++
++                    Rectangle { color: "#91AA9D"; anchors.fill: parent; anchors.margins: 3; radius: 8; smooth: true }
++                    Image { source: "images/qt-logo.png"; anchors.centerIn: parent; smooth: true }
++                }
++
++                MouseArea {
++                    id: mouseArea
++                    anchors.fill: parent
++                    hoverEnabled: true
++
++                    onClicked: {
++                        container.GridView.view.currentIndex = index
++                        container.forceActiveFocus()
++                    }
++                }
++
++                states: State {
++                    name: "active"; when: container.activeFocus
++                    PropertyChanges { target: content; color: "#FCFFF5"; scale: 1.1 }
++                }
++
++                transitions: Transition {
++                    NumberAnimation { properties: "scale"; duration: 100 }
++                }
++            }
++        }
++    }
++}
index 0000000,0000000..7a62f33
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,105 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++FocusScope {
++    clip: true
++
++    onActiveFocusChanged: {
++        if (activeFocus) 
++            mainView.state = "showListViews"
++    }
++
++    ListView {
++        id: list1
++        y: activeFocus ? 10 : 40; width: parent.width / 3; height: parent.height - 20
++        focus: true
++        KeyNavigation.up: gridMenu; KeyNavigation.left: contextMenu; KeyNavigation.right: list2
++        model: 10; cacheBuffer: 200
++        delegate: ListViewDelegate {}
++
++        Behavior on y {
++            NumberAnimation { duration: 600; easing.type: Easing.OutQuint }
++        }
++    }
++
++    ListView {
++        id: list2
++        y: activeFocus ? 10 : 40; x: parseInt(parent.width / 3); width: parent.width / 3; height: parent.height - 20
++        KeyNavigation.up: gridMenu; KeyNavigation.left: list1; KeyNavigation.right: list3
++        model: 10; cacheBuffer: 200
++        delegate: ListViewDelegate {}
++
++        Behavior on y {
++            NumberAnimation { duration: 600; easing.type: Easing.OutQuint }
++        }
++    }
++
++    ListView {
++        id: list3
++        y: activeFocus ? 10 : 40; x: parseInt(2 * parent.width / 3); width: parent.width / 3; height: parent.height - 20
++        KeyNavigation.up: gridMenu; KeyNavigation.left: list2
++        model: 10; cacheBuffer: 200
++        delegate: ListViewDelegate {}
++
++        Behavior on y {
++            NumberAnimation { duration: 600; easing.type: Easing.OutQuint }
++        }
++    }
++
++    Rectangle { width: parent.width; height: 1; color: "#D1DBBD" }
++
++    Rectangle {
++        y: 1; width: parent.width; height: 10
++        gradient: Gradient {
++            GradientStop { position: 0.0; color: "#3E606F" }
++            GradientStop { position: 1.0; color: "transparent" }
++        }
++    }
++
++    Rectangle {
++        y: parent.height - 10; width: parent.width; height: 10
++        gradient: Gradient {
++            GradientStop { position: 1.0; color: "#3E606F" }
++            GradientStop { position: 0.0; color: "transparent" }
++        }
++    }
++}
index 0000000,0000000..b28b026
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,85 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id: container
++    width: ListView.view.width; height: 60; anchors.leftMargin: 10; anchors.rightMargin: 10
++
++    Rectangle {
++        id: content
++        anchors.centerIn: parent; width: container.width - 40; height: container.height - 10
++        color: "transparent"
++        smooth: true
++        radius: 10
++
++        Rectangle { anchors.fill: parent; anchors.margins: 3; color: "#91AA9D"; smooth: true; radius: 8 }
++    }
++
++    Text {
++        id: label
++        anchors.centerIn: content
++        text: "List element " + (index + 1)
++        color: "#193441"
++        font.pixelSize: 14
++    }
++
++    MouseArea {
++        id: mouseArea
++        anchors.fill: parent
++        hoverEnabled: true
++
++        onClicked: {
++            container.ListView.view.currentIndex = index
++            container.forceActiveFocus()
++        }
++    }
++
++    states: State {
++        name: "active"; when: container.activeFocus
++        PropertyChanges { target: content; color: "#FCFFF5"; scale: 1.1 }
++        PropertyChanges { target: label; font.pixelSize: 16 }
++    }
++
++    transitions: Transition {
++        NumberAnimation { properties: "scale"; duration: 100 }
++    }
++}
index 0000000,0000000..14978c2
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..14ddf2a
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..9300ad4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,111 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "Core"
++
++Rectangle {
++    id: window
++    
++    width: 800; height: 480
++    color: "#3E606F"
++
++    FocusScope {
++        id: mainView
++
++        width: parent.width; height: parent.height
++        focus: true
++
++        GridMenu {
++            id: gridMenu
++            width: parent.width; height: 320
++
++            focus: true
++            interactive: parent.activeFocus
++        }
++
++        ListMenu {
++            id: listMenu
++            y: 320; width: parent.width; height: 320
++        }
++
++        Rectangle { 
++            id: shade
++            anchors.fill: parent
++            color: "black"
++            opacity: 0 
++        }
++
++        states: State {
++            name: "showListViews"
++            PropertyChanges { target: gridMenu; y: -160 }
++            PropertyChanges { target: listMenu; y: 160 }
++        }
++
++        transitions: Transition {
++            NumberAnimation { properties: "y"; duration: 600; easing.type: Easing.OutQuint }
++        }
++    }
++
++    Image {
++        source: "Core/images/arrow.png"
++        rotation: 90
++        anchors.verticalCenter: parent.verticalCenter
++
++        MouseArea {
++            anchors.fill: parent; anchors.margins: -10
++            onClicked: contextMenu.focus = true
++        }
++    }
++
++    ContextMenu { id: contextMenu; x: -265; width: 260; height: parent.height }
++
++    states: State {
++        name: "contextMenuOpen"
++        when: !mainView.activeFocus
++        PropertyChanges { target: contextMenu; x: 0; open: true }
++        PropertyChanges { target: mainView; x: 130 }
++        PropertyChanges { target: shade; opacity: 0.25 }
++    }
++
++    transitions: Transition {
++        NumberAnimation { properties: "x,opacity"; duration: 600; easing.type: Easing.OutQuint }
++    }
++}
index 0000000,0000000..f786d93
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++TEMPLATE = app
++TARGET = abstractitemmodel
++DEPENDPATH += .
++INCLUDEPATH += .
++QT += qml quick
++
++HEADERS = model.h
++SOURCES = main.cpp \
++          model.cpp
++RESOURCES += abstractitemmodel.qrc
index 0000000,0000000..4ae861c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,6 @@@
++<!DOCTYPE RCC><RCC version="1.0">
++<qresource>
++    <file>view.qml</file>
++</qresource>
++</RCC>
++
index 0000000,0000000..f5930ce
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,70 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++#include "model.h"
++
++#include <QGuiApplication>
++#include <qqmlengine.h>
++#include <qqmlcontext.h>
++#include <qqml.h>
++#include <QtQuick/qquickitem.h>
++#include <QtQuick/qquickview.h>
++
++//![0]
++int main(int argc, char ** argv)
++{
++    QGuiApplication app(argc, argv);
++
++    AnimalModel model;
++    model.addAnimal(Animal("Wolf", "Medium"));
++    model.addAnimal(Animal("Polar bear", "Large"));
++    model.addAnimal(Animal("Quoll", "Small"));
++
++    QQuickView view;
++    view.setResizeMode(QQuickView::SizeRootObjectToView);
++    QQmlContext *ctxt = view.rootContext();
++    ctxt->setContextProperty("myModel", &model);
++//![0]
++
++    view.setSource(QUrl("qrc:view.qml"));
++    view.show();
++
++    return app.exec();
++}
++
index 0000000,0000000..8f7649c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,90 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++#include "model.h"
++
++Animal::Animal(const QString &type, const QString &size)
++    : m_type(type), m_size(size)
++{
++}
++
++QString Animal::type() const
++{
++    return m_type;
++}
++
++QString Animal::size() const
++{
++    return m_size;
++}
++
++//![0]
++AnimalModel::AnimalModel(QObject *parent)
++    : QAbstractListModel(parent)
++{
++    QHash<int, QByteArray> roles;
++    roles[TypeRole] = "type";
++    roles[SizeRole] = "size";
++    setRoleNames(roles);
++}
++//![0]
++
++void AnimalModel::addAnimal(const Animal &animal)
++{
++    beginInsertRows(QModelIndex(), rowCount(), rowCount());
++    m_animals << animal;
++    endInsertRows();
++}
++
++int AnimalModel::rowCount(const QModelIndex & parent) const {
++    return m_animals.count();
++}
++
++QVariant AnimalModel::data(const QModelIndex & index, int role) const {
++    if (index.row() < 0 || index.row() >= m_animals.count())
++        return QVariant();
++
++    const Animal &animal = m_animals[index.row()];
++    if (role == TypeRole)
++        return animal.type();
++    else if (role == SizeRole)
++        return animal.size();
++    return QVariant();
++}
++
index 0000000,0000000..1378c44
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,83 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++#include <QAbstractListModel>
++#include <QStringList>
++
++//![0]
++class Animal 
++{
++public:
++    Animal(const QString &type, const QString &size);
++//![0]
++
++    QString type() const;
++    QString size() const;
++
++private:
++    QString m_type;
++    QString m_size;
++//![1]
++};
++
++class AnimalModel : public QAbstractListModel
++{
++    Q_OBJECT
++public:
++    enum AnimalRoles {
++        TypeRole = Qt::UserRole + 1,
++        SizeRole
++    };
++
++    AnimalModel(QObject *parent = 0);
++//![1]
++
++    void addAnimal(const Animal &animal);
++
++    int rowCount(const QModelIndex & parent = QModelIndex()) const;
++
++    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
++
++private:
++    QList<Animal> m_animals;
++//![2]
++};
++//![2]
++
++
index 0000000,0000000..64f5871
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,50 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++import QtQuick 2.0
++
++//![0]
++ListView {
++    width: 200; height: 250
++
++    model: myModel
++    delegate: Text { text: "Animal: " + type + ", " + size }
++}
++//![0]
++
index 0000000,0000000..ea3bb5c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,93 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    width: 300; height: 400
++    color: "white"
++
++    ListModel {
++        id: appModel
++        ListElement { name: "Music"; icon: "pics/AudioPlayer_48.png" }
++        ListElement { name: "Movies"; icon: "pics/VideoPlayer_48.png" }
++        ListElement { name: "Camera"; icon: "pics/Camera_48.png" }
++        ListElement { name: "Calendar"; icon: "pics/DateBook_48.png" }
++        ListElement { name: "Messaging"; icon: "pics/EMail_48.png" }
++        ListElement { name: "Todo List"; icon: "pics/TodoList_48.png" }
++        ListElement { name: "Contacts"; icon: "pics/AddressBook_48.png" }
++    }
++
++    Component {
++        id: appDelegate
++
++        Item {
++            width: 100; height: 100
++
++            Image {
++                id: myIcon
++                y: 20; anchors.horizontalCenter: parent.horizontalCenter
++                source: icon
++            }
++            Text {
++                anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter }
++                text: name
++            }
++            MouseArea {
++                anchors.fill: parent
++                onClicked: parent.GridView.view.currentIndex = index
++            }
++        }
++    }
++
++    Component {
++        id: appHighlight
++        Rectangle { width: 80; height: 80; color: "lightsteelblue" }
++    }
++
++    GridView {
++        anchors.fill: parent
++        cellWidth: 100; cellHeight: 100
++        highlight: appHighlight
++        focus: true
++        model: appModel
++        delegate: appDelegate
++    }
++}
index 0000000,0000000..1ab7c8e
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..f4b8689
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..c76b524
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..58f5787
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..d6d84a6
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..0988448
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..52638c5
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..4f2087d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,98 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++ListModel {
++    ListElement {
++        name: "Polly"
++        type: "Parrot"
++        age: 12
++        size: "Small"
++    }
++    ListElement {
++        name: "Penny"
++        type: "Turtle"
++        age: 4
++        size: "Small"
++    }
++    ListElement {
++        name: "Warren"
++        type: "Rabbit"
++        age: 2
++        size: "Small"
++    }
++    ListElement {
++        name: "Spot"
++        type: "Dog"
++        age: 9
++        size: "Medium"
++    }
++    ListElement {
++        name: "Schrödinger"
++        type: "Cat"
++        age: 2
++        size: "Medium"
++    }
++    ListElement {
++        name: "Joey"
++        type: "Kangaroo"
++        age: 1
++        size: "Medium"
++    }
++    ListElement {
++        name: "Kimba"
++        type: "Bunny"
++        age: 65
++        size: "Large"
++    }
++    ListElement {
++        name: "Rover"
++        type: "Dog"
++        age: 5
++        size: "Large"
++    }
++    ListElement {
++        name: "Tiny"
++        type: "Elephant"
++        age: 15
++        size: "Large"
++    }
++}
index 0000000,0000000..b20d8f6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,82 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Image {
++    id: container
++
++    property int repeatDelay: 300
++    property int repeatDuration: 75
++    property bool pressed: false
++
++    signal clicked
++
++    scale: pressed ? 0.9 : 1
++
++    function release() {
++        autoRepeatClicks.stop()
++        container.pressed = false
++    }
++
++    SequentialAnimation on pressed {
++        id: autoRepeatClicks
++        running: false
++
++        PropertyAction { target: container; property: "pressed"; value: true }
++        ScriptAction { script: container.clicked() }
++        PauseAnimation { duration: repeatDelay }
++
++        SequentialAnimation {
++            loops: Animation.Infinite
++            ScriptAction { script: container.clicked() }
++            PauseAnimation { duration: repeatDuration }
++        }
++    }
++
++    MouseArea {
++        anchors.fill: parent
++
++        onPressed: autoRepeatClicks.start()
++        onReleased: container.release()
++        onCanceled: container.release()
++    }
++}
++
index 0000000,0000000..86210ba
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,129 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++ListModel {
++    ListElement {
++        title: "Pancakes"
++        picture: "content/pics/pancakes.jpg"
++        ingredients: "<html> 
++                       <ul> 
++                        <li> 1 cup (150g) self-raising flour 
++                        <li> 1 tbs caster sugar 
++                        <li> 3/4 cup (185ml) milk 
++                        <li> 1 egg 
++                       </ul> 
++                      </html>"
++        method: "<html> 
++                  <ol> 
++                   <li> Sift flour and sugar together into a bowl. Add a pinch of salt. 
++                   <li> Beat milk and egg together, then add to dry ingredients. Beat until smooth. 
++                   <li> Pour mixture into a pan on medium heat and cook until bubbles appear on the surface. 
++                   <li> Turn over and cook other side until golden.  
++                  </ol>
++                 </html>"
++    }
++    ListElement {
++        title: "Fruit Salad"
++        picture: "content/pics/fruit-salad.jpg"
++        ingredients: "* Seasonal Fruit"
++        method: "* Chop fruit and place in a bowl."
++    }
++    ListElement {
++        title: "Vegetable Soup"
++        picture: "content/pics/vegetable-soup.jpg"
++        ingredients: "<html> 
++                       <ul> 
++                        <li> 1 onion 
++                        <li> 1 turnip 
++                        <li> 1 potato 
++                        <li> 1 carrot 
++                        <li> 1 head of celery 
++                        <li> 1 1/2 litres of water 
++                       </ul> 
++                      </html>"
++        method: "<html> 
++                  <ol> 
++                   <li> Chop vegetables. 
++                   <li> Boil in water until vegetables soften. 
++                   <li> Season with salt and pepper to taste. 
++                  </ol> 
++                 </html>"
++    }
++    ListElement {
++        title: "Hamburger"
++        picture: "content/pics/hamburger.jpg"
++        ingredients: "<html> 
++                       <ul> 
++                        <li> 500g minced beef 
++                        <li> Seasoning 
++                        <li> lettuce, tomato, onion, cheese 
++                        <li> 1 hamburger bun for each burger 
++                       </ul> 
++                      </html>"
++        method: "<html> 
++                  <ol> 
++                   <li> Mix the beef, together with seasoning, in a food processor. 
++                   <li> Shape the beef into burgers. 
++                   <li> Grill the burgers for about 5 mins on each side (until cooked through) 
++                   <li> Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion. 
++                  </ol> 
++                 </html>"
++    }
++    ListElement {
++        title: "Lemonade"
++        picture: "content/pics/lemonade.jpg"
++        ingredients: "<html> 
++                       <ul> 
++                        <li> 1 cup Lemon Juice 
++                        <li> 1 cup Sugar 
++                        <li> 6 Cups of Water (2 cups warm water, 4 cups cold water) 
++                       </ul> 
++                      </html>"
++        method: "<html> 
++                  <ol> 
++                   <li> Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves. 
++                   <li> Pour in lemon juice, stir again, and add 4 cups of cold water. 
++                   <li> Chill or serve over ice cubes. 
++                  </ol> 
++                 </html>"
++    }
++}
index 0000000,0000000..980ee21
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,78 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: container
++
++    property alias text: label.text
++
++    signal clicked
++
++    width: label.width + 20; height: label.height + 6
++    smooth: true
++    radius: 10
++
++    gradient: Gradient {
++        GradientStop { id: gradientStop; position: 0.0; color: palette.light }
++        GradientStop { position: 1.0; color: palette.button }
++    }
++
++    SystemPalette { id: palette }
++
++    MouseArea {
++        id: mouseArea
++        anchors.fill: parent
++        onClicked: { container.clicked() }
++    }
++
++    Text {
++        id: label
++        anchors.centerIn: parent
++    }
++
++    states: State {
++        name: "pressed"
++        when: mouseArea.pressed
++        PropertyChanges { target: gradientStop; color: palette.dark }
++    }
++}
++
index 0000000,0000000..52f4988
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,58 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the QtQml module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: root
++    property alias label: text.text
++    property bool active: false
++    signal toggled
++    width: 149
++    height: 30
++    radius: 3
++    color: active ? "green" : "lightgray"
++    border.width: 1
++    Text { id: text; anchors.centerIn: parent; font.pixelSize: 14 }
++    MouseArea {
++        anchors.fill: parent
++        onClicked: { active = !active; root.toggled() }
++    }
++}
index 0000000,0000000..29d1d44
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..e437312
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..da5a6b1
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..d0a15be
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..db445c9
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..df2a147
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..d6f233d
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..31a35d5
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..fefb9c9
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..60c4396
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..40df113
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..9dce332
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..ee7c632
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,203 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++import QtQuick 2.0
++import "content"
++
++// This example shows how items can be dynamically added to and removed from
++// a ListModel, and how these list modifications can be animated.
++
++Rectangle {
++    id: container
++    width: 500; height: 400
++    color: "#343434"
++
++    // The model:
++    ListModel {
++        id: fruitModel
++
++        ListElement {
++            name: "Apple"; cost: 2.45
++            attributes: [
++                ListElement { description: "Core" },
++                ListElement { description: "Deciduous" }
++            ]
++        }
++        ListElement {
++            name: "Banana"; cost: 1.95
++            attributes: [
++                ListElement { description: "Tropical" },
++                ListElement { description: "Seedless" }
++            ]
++        }
++        ListElement {
++            name: "Cumquat"; cost: 3.25
++            attributes: [
++                ListElement { description: "Citrus" }
++            ]
++        }
++        ListElement {
++            name: "Durian"; cost: 9.95
++            attributes: [
++                ListElement { description: "Tropical" },
++                ListElement { description: "Smelly" }
++            ]
++        }
++    }
++
++    // The delegate for each fruit in the model:
++    Component {
++        id: listDelegate
++        
++        Item {
++            id: delegateItem
++            width: listView.width; height: 55
++            clip: true
++
++            Row {
++                anchors.verticalCenter: parent.verticalCenter
++                spacing: 10
++
++                Column {
++                    Image {
++                        source: "content/pics/arrow-up.png"
++                        MouseArea { anchors.fill: parent; onClicked: fruitModel.move(index, index-1, 1) }
++                    }
++                    Image { source: "content/pics/arrow-down.png"
++                        MouseArea { anchors.fill: parent; onClicked: fruitModel.move(index, index+1, 1) }
++                    }
++                }
++
++                Column {
++                    anchors.verticalCenter: parent.verticalCenter
++
++                    Text { 
++                        text: name
++                        font.pixelSize: 15
++                        color: "white"
++                    }
++                    Row {
++                        spacing: 5
++                        Repeater {
++                            model: attributes
++                            Text { text: description; color: "White" }
++                        }
++                    }
++                }
++            }
++
++            Row {
++                anchors.verticalCenter: parent.verticalCenter
++                anchors.right: parent.right
++                spacing: 10
++
++                PressAndHoldButton {
++                    anchors.verticalCenter: parent.verticalCenter
++                    source: "content/pics/plus-sign.png"
++                    onClicked: fruitModel.setProperty(index, "cost", cost + 0.25)
++                }
++
++                Text { 
++                    id: costText
++                    anchors.verticalCenter: parent.verticalCenter
++                    text: '$' + Number(cost).toFixed(2)
++                    font.pixelSize: 15
++                    color: "white"
++                    font.bold: true
++                }
++
++                PressAndHoldButton {
++                    anchors.verticalCenter: parent.verticalCenter
++                    source: "content/pics/minus-sign.png"
++                    onClicked: fruitModel.setProperty(index, "cost", Math.max(0,cost-0.25))
++                }
++
++                Image {
++                    source: "content/pics/list-delete.png"
++                    MouseArea { anchors.fill:parent; onClicked: fruitModel.remove(index) }
++                }
++            }
++
++            // Animate adding and removing of items:
++
++            ListView.onAdd: SequentialAnimation {
++                PropertyAction { target: delegateItem; property: "height"; value: 0 }
++                NumberAnimation { target: delegateItem; property: "height"; to: 55; duration: 250; easing.type: Easing.InOutQuad }
++            }
++
++            ListView.onRemove: SequentialAnimation {
++                PropertyAction { target: delegateItem; property: "ListView.delayRemove"; value: true }
++                NumberAnimation { target: delegateItem; property: "height"; to: 0; duration: 250; easing.type: Easing.InOutQuad }
++
++                // Make sure delayRemove is set back to false so that the item can be destroyed
++                PropertyAction { target: delegateItem; property: "ListView.delayRemove"; value: false }
++            }
++        }
++    }
++
++    // The view:
++    ListView {
++        id: listView
++        anchors.fill: parent; anchors.margins: 20
++        model: fruitModel
++        delegate: listDelegate
++    }
++
++    Row {
++        anchors { left: parent.left; bottom: parent.bottom; margins: 20 }
++        spacing: 10
++
++        TextButton { 
++            text: "Add an item"
++            onClicked: {
++                fruitModel.append({
++                    "name": "Pizza Margarita",
++                    "cost": 5.95,
++                    "attributes": [{"description": "Cheese"}, {"description": "Tomato"}]
++                })
++            }
++        }
++
++        TextButton { 
++            text: "Remove all items" 
++            onClicked: fruitModel.clear()
++        }
++    }
++}
++
index 0000000,0000000..43a9662
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,202 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "content"
++
++// This example illustrates expanding a list item to show a more detailed view.
++
++Rectangle {
++    id: page
++    width: 400; height: 240
++    color: "black"
++
++    // Delegate for the recipes.  This delegate has two modes:
++    // 1. List mode (default), which just shows the picture and title of the recipe.
++    // 2. Details mode, which also shows the ingredients and method.
++    Component {
++        id: recipeDelegate
++
++        Item {
++            id: recipe
++
++            // Create a property to contain the visibility of the details.
++            // We can bind multiple element's opacity to this one property,
++            // rather than having a "PropertyChanges" line for each element we
++            // want to fade.
++            property real detailsOpacity : 0
++
++            width: listView.width
++            height: 70
++
++            // A simple rounded rectangle for the background
++            Rectangle {
++                id: background
++                x: 2; y: 2; width: parent.width - x*2; height: parent.height - y*2
++                color: "ivory"
++                border.color: "orange"
++                radius: 5
++            }
++
++            // This mouse region covers the entire delegate.
++            // When clicked it changes mode to 'Details'.  If we are already
++            // in Details mode, then no change will happen.
++            MouseArea {
++                anchors.fill: parent
++                onClicked: recipe.state = 'Details';
++            }
++
++            // Lay out the page: picture, title and ingredients at the top, and method at the
++            // bottom.  Note that elements that should not be visible in the list
++            // mode have their opacity set to recipe.detailsOpacity.
++            Row {
++                id: topLayout
++                x: 10; y: 10; height: recipeImage.height; width: parent.width
++                spacing: 10
++
++                Image {
++                    id: recipeImage
++                    width: 50; height: 50
++                    source: picture
++                }
++
++                Column {
++                    width: background.width - recipeImage.width - 20; height: recipeImage.height
++                    spacing: 5
++
++                    Text { 
++                        text: title
++                        font.bold: true; font.pointSize: 16
++                    }
++
++                    Text {
++                        text: "Ingredients"
++                        font.pointSize: 12; font.bold: true
++                        opacity: recipe.detailsOpacity
++                    }
++
++                    Text {
++                        text: ingredients
++                        wrapMode: Text.WordWrap
++                        width: parent.width
++                        opacity: recipe.detailsOpacity
++                    }
++                }
++            }
++
++            Item {
++                id: details
++                x: 10; width: parent.width - 20
++                anchors { top: topLayout.bottom; topMargin: 10; bottom: parent.bottom; bottomMargin: 10 }
++                opacity: recipe.detailsOpacity
++
++                Text {
++                    id: methodTitle
++                    anchors.top: parent.top
++                    text: "Method"
++                    font.pointSize: 12; font.bold: true
++                }
++
++                Flickable {
++                    id: flick
++                    width: parent.width
++                    anchors { top: methodTitle.bottom; bottom: parent.bottom }
++                    contentHeight: methodText.height
++                    clip: true
++
++                    Text { id: methodText; text: method; wrapMode: Text.WordWrap; width: details.width }
++                }
++
++                Image {
++                    anchors { right: flick.right; top: flick.top }
++                    source: "content/pics/moreUp.png"
++                    opacity: flick.atYBeginning ? 0 : 1
++                }
++
++                Image {
++                    anchors { right: flick.right; bottom: flick.bottom }
++                    source: "content/pics/moreDown.png"
++                    opacity: flick.atYEnd ? 0 : 1
++                }
++            }
++
++            // A button to close the detailed view, i.e. set the state back to default ('').
++            TextButton {
++                y: 10
++                anchors { right: background.right; rightMargin: 10 }
++                opacity: recipe.detailsOpacity
++                text: "Close"
++
++                onClicked: recipe.state = '';
++            }
++
++            states: State {
++                name: "Details"
++
++                PropertyChanges { target: background; color: "white" }
++                PropertyChanges { target: recipeImage; width: 130; height: 130 } // Make picture bigger
++                PropertyChanges { target: recipe; detailsOpacity: 1; x: 0 } // Make details visible
++                PropertyChanges { target: recipe; height: listView.height } // Fill the entire list area with the detailed view
++
++                // Move the list so that this item is at the top.
++                PropertyChanges { target: recipe.ListView.view; explicit: true; contentY: recipe.y }
++
++                // Disallow flicking while we're in detailed view
++                PropertyChanges { target: recipe.ListView.view; interactive: false }
++            }
++
++            transitions: Transition {
++                // Make the state changes smooth
++                ParallelAnimation {
++                    ColorAnimation { property: "color"; duration: 500 }
++                    NumberAnimation { duration: 300; properties: "detailsOpacity,x,contentY,height,width" }
++                }
++            }
++        }
++    }
++
++    // The actual list
++    ListView {
++        id: listView
++        anchors.fill: parent
++        model: RecipesModel {}
++        delegate: recipeDelegate
++    }
++}
index 0000000,0000000..d8f7608
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,99 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++// This example shows how to create your own highlight delegate for a ListView
++// that uses a SpringAnimation to provide custom movement when the
++// highlight bar is moved between items.
++
++import QtQuick 2.0
++import "content"
++
++Rectangle {
++    width: 200; height: 300
++
++    // Define a delegate component.  A component will be
++    // instantiated for each visible item in the list.
++    Component {
++        id: petDelegate
++        Item {
++            id: wrapper
++            width: 200; height: 55
++            Column {
++                Text { text: 'Name: ' + name }
++                Text { text: 'Type: ' + type }
++                Text { text: 'Age: ' + age }
++            }
++            // indent the item if it is the current item
++            states: State {
++                name: "Current"
++                when: wrapper.ListView.isCurrentItem
++                PropertyChanges { target: wrapper; x: 20 }
++            }
++            transitions: Transition {
++                NumberAnimation { properties: "x"; duration: 200 } 
++            }
++        }
++    }
++
++    // Define a highlight with customised movement between items.
++    Component {
++        id: highlightBar
++        Rectangle {
++            width: 200; height: 50
++            color: "#FFFF88"
++            y: listView.currentItem.y;
++            Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } }
++        }
++    }
++
++    ListView {
++        id: listView
++        width: 200; height: parent.height
++
++        model: PetsModel {}
++        delegate: petDelegate
++        focus: true
++
++        // Set the highlight delegate. Note we must also set highlightFollowsCurrentItem
++        // to false so the highlight delegate can control how the highlight is moved.
++        highlight: highlightBar
++        highlightFollowsCurrentItem: false
++    }
++}
index 0000000,0000000..a536ddc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,122 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "content"
++
++Rectangle {
++    id: root
++    property int current: 0
++    width: 600; height: 300
++
++    // This example shows the same model in three different ListView items, 
++    // with different highlight ranges. The highlight ranges are set by the 
++    // preferredHighlightBegin and preferredHighlightEnd properties in ListView.
++    //
++    // The first ListView does not set a highlight range, so its currentItem
++    // can move freely within the visible area. If it moves outside the
++    // visible area, the view is automatically scrolled to keep the current
++    // item visible.
++    //
++    // The second ListView sets a highlight range which attempts to keep the
++    // current item within the the bounds of the range. However,
++    // items will not scroll beyond the beginning or end of the view,
++    // forcing the highlight to move outside the range at the ends.
++    //
++    // The third ListView sets the highlightRangeMode to StrictlyEnforceRange
++    // and sets a range smaller than the height of an item.  This
++    // forces the current item to change when the view is flicked,
++    // since the highlight is unable to move.
++    //
++    // All ListViews bind their currentIndex to the root.current property.
++    // The first ListView sets root.current whenever its currentIndex changes
++    // due to keyboard interaction.
++    // Flicking the third ListView with the mouse also changes root.current.
++
++    ListView {
++        id: list1
++        width: 200; height: parent.height
++        model: PetsModel {}
++        delegate: petDelegate
++
++        highlight: Rectangle { color: "lightsteelblue" }
++        currentIndex: root.current
++        onCurrentIndexChanged: root.current = currentIndex
++        focus: true
++    }
++
++    ListView {
++        id: list2
++        x: list1.width
++        width: 200; height: parent.height
++        model: PetsModel {}
++        delegate: petDelegate
++
++        highlight: Rectangle { color: "yellow" }
++        currentIndex: root.current
++        preferredHighlightBegin: 80; preferredHighlightEnd: 220
++        highlightRangeMode: ListView.ApplyRange
++    }
++
++    ListView {
++        id: list3
++        x: list1.width + list2.width
++        width: 200; height: parent.height
++        model: PetsModel {}
++        delegate: petDelegate
++
++        highlight: Rectangle { color: "yellow" }
++        currentIndex: root.current
++        onCurrentIndexChanged: root.current = currentIndex
++        preferredHighlightBegin: 125; preferredHighlightEnd: 125
++        highlightRangeMode: ListView.StrictlyEnforceRange
++    }
++
++    // The delegate for each list
++    Component {
++        id: petDelegate
++        Column {
++            width: 200
++            Text { text: 'Name: ' + name }
++            Text { text: 'Type: ' + type }
++            Text { text: 'Age: ' + age }
++        }
++    }
++}
index 0000000,0000000..2e63a86
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,127 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++// This example shows how a ListView can be separated into sections using
++// the ListView.section attached property.
++
++import QtQuick 2.0
++import "content"
++
++Rectangle {
++    id: container
++    width: 300
++    height: 360
++
++    ListModel {
++        id: animalsModel
++        ListElement { name: "Ant"; size: "Tiny" }
++        ListElement { name: "Flea"; size: "Tiny" }
++        ListElement { name: "Parrot"; size: "Small" }
++        ListElement { name: "Guinea pig"; size: "Small" }
++        ListElement { name: "Rat"; size: "Small" }
++        ListElement { name: "Butterfly"; size: "Small" }
++        ListElement { name: "Dog"; size: "Medium" }
++        ListElement { name: "Cat"; size: "Medium" }
++        ListElement { name: "Pony"; size: "Medium" }
++        ListElement { name: "Koala"; size: "Medium" }
++        ListElement { name: "Horse"; size: "Large" }
++        ListElement { name: "Tiger"; size: "Large" }
++        ListElement { name: "Giraffe"; size: "Large" }
++        ListElement { name: "Elephant"; size: "Huge" }
++        ListElement { name: "Whale"; size: "Huge" }
++    }
++
++//! [0]
++    // The delegate for each section header
++    Component { 
++        id: sectionHeading
++        Rectangle {
++            width: container.width
++            height: childrenRect.height
++            color: "lightsteelblue"
++
++            Text {
++                text: section
++                font.bold: true
++                font.pixelSize: 20
++            }
++        }
++    }
++
++    ListView {
++        id: view
++        anchors.top: parent.top
++        anchors.bottom: buttonBar.top
++        width: parent.width
++        model: animalsModel
++        delegate: Text { text: name; font.pixelSize: 18 }
++
++        section.property: "size"
++        section.criteria: ViewSection.FullString
++        section.delegate: sectionHeading
++    }
++//! [0]
++
++    Row {
++        id: buttonBar
++        anchors.bottom: parent.bottom
++        anchors.bottomMargin: 1
++        spacing: 1
++        ToggleButton {
++            label: "CurrentLabelAtStart"
++            onToggled: {
++                if (active)
++                    view.section.labelPositioning |= ViewSection.CurrentLabelAtStart
++                else
++                    view.section.labelPositioning &= ~ViewSection.CurrentLabelAtStart
++            }
++        }
++        ToggleButton {
++            label: "NextLabelAtEnd"
++            onToggled: {
++                if (active)
++                    view.section.labelPositioning |= ViewSection.NextLabelAtEnd
++                else
++                    view.section.labelPositioning &= ~ViewSection.NextLabelAtEnd
++            }
++        }
++    }
++}
++
index 0000000,0000000..7748da0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,8 @@@
++TEMPLATE = subdirs
++
++SUBDIRS += \
++    abstractitemmodel \
++    objectlistmodel \
++    stringlistmodel
++
++
index 0000000,0000000..40f9e56
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++import QmlProject 1.1
++
++Project {
++    mainFile: "modelviews.qml"
++
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..7216283
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,78 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <QDebug>
++#include "dataobject.h"
++
++DataObject::DataObject(QObject *parent)
++    : QObject(parent)
++{
++}
++
++DataObject::DataObject(const QString &name, const QString &color, QObject *parent)
++    : QObject(parent), m_name(name), m_color(color)
++{
++}
++
++QString DataObject::name() const
++{
++    return m_name;
++}
++
++void DataObject::setName(const QString &name)
++{
++    if (name != m_name) {
++        m_name = name;
++        emit nameChanged();
++    }
++}
++
++QString DataObject::color() const
++{
++    return m_color;
++}
++
++void DataObject::setColor(const QString &color)
++{
++    if (color != m_color) {
++        m_color = color;
++        emit colorChanged();
++    }
++}
index 0000000,0000000..bea92a2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,76 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#ifndef DATAOBJECT_H
++#define DATAOBJECT_H
++
++#include <QObject>
++
++//![0]
++class DataObject : public QObject
++{
++    Q_OBJECT
++
++    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
++    Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
++//![0]
++
++public:
++    DataObject(QObject *parent=0);
++    DataObject(const QString &name, const QString &color, QObject *parent=0);
++
++    QString name() const;
++    void setName(const QString &name);
++
++    QString color() const;
++    void setColor(const QString &color);
++
++signals:
++    void nameChanged();
++    void colorChanged();
++
++private:
++    QString m_name;
++    QString m_color;
++//![1]
++};
++//![1]
++
++#endif // DATAOBJECT_H
index 0000000,0000000..bb3895f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,78 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the demonstration applications of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <QGuiApplication>
++
++#include <qqmlengine.h>
++#include <qqmlcontext.h>
++#include <qqml.h>
++#include <QtQuick/qquickitem.h>
++#include <QtQuick/qquickview.h>
++
++#include "dataobject.h"
++
++/*
++   This example illustrates exposing a QList<QObject*> as a
++   model in QML
++*/
++
++//![0]
++int main(int argc, char ** argv)
++{
++    QGuiApplication app(argc, argv);
++
++    QList<QObject*> dataList;
++    dataList.append(new DataObject("Item 1", "red"));
++    dataList.append(new DataObject("Item 2", "green"));
++    dataList.append(new DataObject("Item 3", "blue"));
++    dataList.append(new DataObject("Item 4", "yellow"));
++
++    QQuickView view;
++    view.setResizeMode(QQuickView::SizeRootObjectToView);
++    QQmlContext *ctxt = view.rootContext();
++    ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
++//![0]
++
++    view.setSource(QUrl("qrc:view.qml"));
++    view.show();
++
++    return app.exec();
++}
++
index 0000000,0000000..7f323c3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,6 @@@
++QT += qml quick
++
++SOURCES += main.cpp \
++           dataobject.cpp
++HEADERS += dataobject.h
++RESOURCES += objectlistmodel.qrc
index 0000000,0000000..2bb4016
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,14 @@@
++import QmlProject 1.0
++
++Project {
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..17e9301
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++<!DOCTYPE RCC><RCC version="1.0">
++<qresource>
++    <file>view.qml</file>
++</qresource>
++</RCC>
index 0000000,0000000..3954e79
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,55 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++//![0]
++ListView {
++    width: 100; height: 100
++
++    model: myModel
++    delegate: Rectangle {
++        height: 25
++        width: 100
++        color: model.modelData.color
++        Text { text: name }
++    }
++}
++//![0]
index 0000000,0000000..97c7840
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,88 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++//![0]
++Package {
++    Text { id: listDelegate; width: 200; height: 25; text: 'Empty'; Package.name: 'list' }
++    Text { id: gridDelegate; width: 100; height: 50; text: 'Empty'; Package.name: 'grid' }
++
++    Rectangle {
++        id: wrapper
++        width: 200; height: 25
++        color: 'lightsteelblue'
++
++        Text { text: display; anchors.centerIn: parent }
++        MouseArea {
++            anchors.fill: parent
++            onClicked: {
++                if (wrapper.state == 'inList')
++                    wrapper.state = 'inGrid';
++                else
++                    wrapper.state = 'inList';
++            }
++        }
++
++        state: 'inList'
++        states: [
++            State {
++                name: 'inList'
++                ParentChange { target: wrapper; parent: listDelegate }
++            },
++            State {
++                name: 'inGrid'
++                ParentChange {
++                    target: wrapper; parent: gridDelegate
++                    x: 0; y: 0; width: gridDelegate.width; height: gridDelegate.height
++                }
++            }
++        ]
++
++        transitions: [
++            Transition {
++                ParentAnimation {
++                    NumberAnimation { properties: 'x,y,width,height'; duration: 300 }
++                }
++            }
++        ]
++    }
++}
++//![0]
index 0000000,0000000..7f0e8cb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,143 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id : clock
++    width: {
++        if (ListView.view && ListView.view.width >= 200)
++            return ListView.view.width / Math.floor(ListView.view.width / 200.0);
++        else
++            return 200;
++    }
++
++    height: {
++        if (ListView.view && ListView.view.height >= 240)
++            return ListView.view.height;
++        else
++            return 240;
++    }
++
++    property alias city: cityLabel.text
++    property int hours
++    property int minutes
++    property int seconds
++    property real shift
++    property bool night: false
++    property bool internationalTime: true //Unset for local time
++
++    function timeChanged() {
++        var date = new Date;
++        hours = internationalTime ? date.getUTCHours() + Math.floor(clock.shift) : date.getHours()
++        night = ( hours < 7 || hours > 19 )
++        minutes = internationalTime ? date.getUTCMinutes() + ((clock.shift % 1) * 60) : date.getMinutes()
++        seconds = date.getUTCSeconds();
++    }
++
++    Timer {
++        interval: 100; running: true; repeat: true;
++        onTriggered: clock.timeChanged()
++    }
++
++    Item {
++        anchors.centerIn: parent
++        width: 200; height: 240
++
++        Image { id: background; source: "clock.png"; visible: clock.night == false }
++        Image { source: "clock-night.png"; visible: clock.night == true }
++
++
++        Image {
++            x: 92.5; y: 27
++            source: "hour.png"
++            smooth: true
++            transform: Rotation {
++                id: hourRotation
++                origin.x: 7.5; origin.y: 73;
++                angle: (clock.hours * 30) + (clock.minutes * 0.5)
++                Behavior on angle {
++                    SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
++                }
++            }
++        }
++
++        Image {
++            x: 93.5; y: 17
++            source: "minute.png"
++            smooth: true
++            transform: Rotation {
++                id: minuteRotation
++                origin.x: 6.5; origin.y: 83;
++                angle: clock.minutes * 6
++                Behavior on angle {
++                    SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
++                }
++            }
++        }
++
++        Image {
++            x: 97.5; y: 20
++            source: "second.png"
++            smooth: true
++            transform: Rotation {
++                id: secondRotation
++                origin.x: 2.5; origin.y: 80;
++                angle: clock.seconds * 6
++                Behavior on angle {
++                    SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
++                }
++            }
++        }
++
++        Image {
++            anchors.centerIn: background; source: "center.png"
++        }
++
++        Text {
++            id: cityLabel
++            y: 210; anchors.horizontalCenter: parent.horizontalCenter
++            color: "white"
++            font.family: "Helvetica"
++            font.bold: true; font.pixelSize: 16
++            style: Text.Raised; styleColor: "black"
++        }
++    }
++}
index 0000000,0000000..2acf50d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,123 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id: root
++
++    property alias background: background.source
++    property int currentIndex: 0
++    default property alias content: visualModel.children
++
++    Image {
++        id: background
++        fillMode: Image.TileHorizontally
++        x: -list.contentX / 2
++        width: Math.max(list.contentWidth, parent.width)
++    }
++
++    ListView {
++        id: list
++        anchors.fill: parent
++
++        currentIndex: root.currentIndex
++        onCurrentIndexChanged: root.currentIndex = currentIndex
++
++        orientation: Qt.Horizontal
++        boundsBehavior: Flickable.DragOverBounds
++        model: VisualItemModel { id: visualModel }
++
++        highlightRangeMode: ListView.StrictlyEnforceRange
++        snapMode: ListView.SnapOneItem
++    }
++
++    ListView {
++        id: selector
++
++        height: 50
++        anchors.bottom: parent.bottom
++        anchors.horizontalCenter: parent.horizontalCenter
++        width: Math.min(count * 50, parent.width - 20)
++        interactive: width == parent.width - 20
++        orientation: Qt.Horizontal
++
++        currentIndex: root.currentIndex
++        onCurrentIndexChanged: root.currentIndex = currentIndex
++
++        model: visualModel.children
++        delegate: Item {
++            width: 50; height: 50
++            id: delegateRoot
++
++            Image {
++                id: image
++                source: modelData.icon
++                smooth: true
++                scale: 0.8
++            }
++
++            MouseArea {
++                anchors.fill: parent
++                onClicked: { root.currentIndex = index }
++            }
++
++            states: State {
++                name: "Selected"
++                when: delegateRoot.ListView.isCurrentItem == true
++                PropertyChanges {
++                    target: image
++                    scale: 1
++                    y: -5
++                }
++            }
++            transitions: Transition {
++                NumberAnimation { properties: "scale,y" }
++            }
++        }
++
++        Rectangle {
++            color: "#60FFFFFF"
++            x: -10; y: -10; z: -1
++            width: parent.width + 20; height: parent.height + 20
++            radius: 10
++        }
++    }
++}
index 0000000,0000000..702b892
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,52 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++Image {
++    source: "quit.png"
++    scale: quitMouse.pressed ? 0.8 : 1.0
++    smooth: quitMouse.pressed
++    MouseArea {
++        id: quitMouse
++        anchors.fill: parent
++        anchors.margins: -10
++        onClicked: Qt.quit()
++    }
++}
index 0000000,0000000..982b6c5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,84 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++// This is taken from the declarative animation/basics/property-animation.qml
++// example
++
++Item {
++    id: window
++    width: 320; height: 480
++
++    Image {
++        anchors.horizontalCenter: parent.horizontalCenter
++        y: smiley.minHeight + 58
++        source: "pics/shadow.png"
++
++        scale: smiley.y * 0.5 / (smiley.minHeight - smiley.maxHeight)
++    }
++
++    Image {
++        id: smiley
++        property int maxHeight: window.height / 3
++        property int minHeight: 2 * window.height / 3
++
++        anchors.horizontalCenter: parent.horizontalCenter
++        y: minHeight
++        source: "pics/face-smile.png"
++
++        SequentialAnimation on y {
++            loops: Animation.Infinite
++
++            NumberAnimation {
++                from: smiley.minHeight; to: smiley.maxHeight
++                easing.type: Easing.OutExpo; duration: 300
++            }
++
++            NumberAnimation {
++                from: smiley.maxHeight; to: smiley.minHeight
++                easing.type: Easing.OutBounce; duration: 1000
++            }
++
++            PauseAnimation { duration: 500 }
++        }
++    }
++}
++
index 0000000,0000000..a885950
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..7fbd802
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..cc7151a
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..462edac
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..f8061a1
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..1297ec7
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..61cca2f
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..3d66d72
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..bd090c3
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..4f16958
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,445 @@@
++<?xml version="1.0" encoding="UTF-8" standalone="no"?>
++<svg
++   xmlns:dc="http://purl.org/dc/elements/1.1/"
++   xmlns:cc="http://creativecommons.org/ns#"
++   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
++   xmlns:svg="http://www.w3.org/2000/svg"
++   xmlns="http://www.w3.org/2000/svg"
++   xmlns:xlink="http://www.w3.org/1999/xlink"
++   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
++   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
++   width="48"
++   height="48"
++   overflow="visible"
++   enable-background="new 0 0 128 129.396"
++   xml:space="preserve"
++   id="svg2"
++   sodipodi:version="0.32"
++   inkscape:version="0.46"
++   sodipodi:docname="go-home.svg"
++   sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
++   version="1.0"
++   inkscape:export-filename="/home/tigert/My Downloads/go-home.png"
++   inkscape:export-xdpi="90.000000"
++   inkscape:export-ydpi="90.000000"
++   inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
++   id="metadata367"><rdf:RDF><cc:Work
++       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
++         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><cc:license
++         rdf:resource="http://creativecommons.org/licenses/publicdomain/" /><dc:title>Go Home</dc:title><dc:creator><cc:Agent><dc:title>Jakub Steiner</dc:title></cc:Agent></dc:creator><dc:source>http://jimmac.musichall.cz</dc:source><dc:subject><rdf:Bag><rdf:li>home</rdf:li><rdf:li>return</rdf:li><rdf:li>go</rdf:li><rdf:li>default</rdf:li><rdf:li>user</rdf:li><rdf:li>directory</rdf:li></rdf:Bag></dc:subject><dc:contributor><cc:Agent><dc:title>Tuomas Kuosmanen</dc:title></cc:Agent></dc:contributor></cc:Work><cc:License
++       rdf:about="http://creativecommons.org/licenses/publicdomain/"><cc:permits
++         rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
++         rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:permits
++         rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /></cc:License></rdf:RDF></metadata><defs
++   id="defs365"><inkscape:perspective
++     sodipodi:type="inkscape:persp3d"
++     inkscape:vp_x="0 : 24 : 1"
++     inkscape:vp_y="0 : 1000 : 0"
++     inkscape:vp_z="48 : 24 : 1"
++     inkscape:persp3d-origin="24 : 16 : 1"
++     id="perspective92" /><radialGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient5060"
++     id="radialGradient5031"
++     gradientUnits="userSpaceOnUse"
++     gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
++     cx="605.71429"
++     cy="486.64789"
++     fx="605.71429"
++     fy="486.64789"
++     r="117.14286" /><linearGradient
++     inkscape:collect="always"
++     id="linearGradient5060"><stop
++       style="stop-color:black;stop-opacity:1;"
++       offset="0"
++       id="stop5062" /><stop
++       style="stop-color:black;stop-opacity:0;"
++       offset="1"
++       id="stop5064" /></linearGradient><radialGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient5060"
++     id="radialGradient5029"
++     gradientUnits="userSpaceOnUse"
++     gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
++     cx="605.71429"
++     cy="486.64789"
++     fx="605.71429"
++     fy="486.64789"
++     r="117.14286" /><linearGradient
++     id="linearGradient5048"><stop
++       style="stop-color:black;stop-opacity:0;"
++       offset="0"
++       id="stop5050" /><stop
++       id="stop5056"
++       offset="0.5"
++       style="stop-color:black;stop-opacity:1;" /><stop
++       style="stop-color:black;stop-opacity:0;"
++       offset="1"
++       id="stop5052" /></linearGradient><linearGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient5048"
++     id="linearGradient5027"
++     gradientUnits="userSpaceOnUse"
++     gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
++     x1="302.85715"
++     y1="366.64789"
++     x2="302.85715"
++     y2="609.50507" /><linearGradient
++     id="linearGradient2406"><stop
++       style="stop-color:#7c7e79;stop-opacity:1;"
++       offset="0"
++       id="stop2408" /><stop
++       id="stop2414"
++       offset="0.1724138"
++       style="stop-color:#848681;stop-opacity:1;" /><stop
++       style="stop-color:#898c86;stop-opacity:1;"
++       offset="1"
++       id="stop2410" /></linearGradient><linearGradient
++     inkscape:collect="always"
++     id="linearGradient2390"><stop
++       style="stop-color:#919191;stop-opacity:1;"
++       offset="0"
++       id="stop2392" /><stop
++       style="stop-color:#919191;stop-opacity:0;"
++       offset="1"
++       id="stop2394" /></linearGradient><linearGradient
++     inkscape:collect="always"
++     id="linearGradient2378"><stop
++       style="stop-color:#575757;stop-opacity:1;"
++       offset="0"
++       id="stop2380" /><stop
++       style="stop-color:#575757;stop-opacity:0;"
++       offset="1"
++       id="stop2382" /></linearGradient><linearGradient
++     inkscape:collect="always"
++     id="linearGradient2368"><stop
++       style="stop-color:#ffffff;stop-opacity:1;"
++       offset="0"
++       id="stop2370" /><stop
++       style="stop-color:#ffffff;stop-opacity:0;"
++       offset="1"
++       id="stop2372" /></linearGradient><linearGradient
++     inkscape:collect="always"
++     id="linearGradient2349"><stop
++       style="stop-color:#000000;stop-opacity:1;"
++       offset="0"
++       id="stop2351" /><stop
++       style="stop-color:#000000;stop-opacity:0;"
++       offset="1"
++       id="stop2353" /></linearGradient><linearGradient
++     id="linearGradient2341"><stop
++       id="stop2343"
++       offset="0"
++       style="stop-color:#000000;stop-opacity:1;" /><stop
++       id="stop2345"
++       offset="1"
++       style="stop-color:#000000;stop-opacity:0;" /></linearGradient><linearGradient
++     id="linearGradient2329"><stop
++       style="stop-color:#000000;stop-opacity:0.18556701;"
++       offset="0"
++       id="stop2331" /><stop
++       style="stop-color:#ffffff;stop-opacity:1;"
++       offset="1"
++       id="stop2333" /></linearGradient><linearGradient
++     inkscape:collect="always"
++     id="linearGradient2319"><stop
++       style="stop-color:#000000;stop-opacity:1;"
++       offset="0"
++       id="stop2321" /><stop
++       style="stop-color:#000000;stop-opacity:0;"
++       offset="1"
++       id="stop2323" /></linearGradient><linearGradient
++     id="linearGradient2307"><stop
++       style="stop-color:#edd400;stop-opacity:1;"
++       offset="0"
++       id="stop2309" /><stop
++       style="stop-color:#998800;stop-opacity:1;"
++       offset="1"
++       id="stop2311" /></linearGradient><linearGradient
++     inkscape:collect="always"
++     id="linearGradient2299"><stop
++       style="stop-color:#ffffff;stop-opacity:1;"
++       offset="0"
++       id="stop2301" /><stop
++       style="stop-color:#ffffff;stop-opacity:0;"
++       offset="1"
++       id="stop2303" /></linearGradient><linearGradient
++     id="XMLID_2_"
++     gradientUnits="userSpaceOnUse"
++     x1="80.223602"
++     y1="117.5205"
++     x2="48.046001"
++     y2="59.7995"
++     gradientTransform="matrix(0.314683,0.000000,0.000000,0.314683,4.128264,3.742874)">
++                              <stop
++   offset="0"
++   style="stop-color:#CCCCCC"
++   id="stop17" />
++                              <stop
++   offset="0.9831"
++   style="stop-color:#FFFFFF"
++   id="stop19" />
++                              <midPointStop
++   offset="0"
++   style="stop-color:#CCCCCC"
++   id="midPointStop48" />
++                              <midPointStop
++   offset="0.5"
++   style="stop-color:#CCCCCC"
++   id="midPointStop50" />
++                              <midPointStop
++   offset="0.9831"
++   style="stop-color:#FFFFFF"
++   id="midPointStop52" />
++                      </linearGradient><linearGradient
++     inkscape:collect="always"
++     xlink:href="#XMLID_2_"
++     id="linearGradient1514"
++     gradientUnits="userSpaceOnUse"
++     gradientTransform="matrix(0.336922,0.000000,0.000000,0.166888,17.98288,15.46151)"
++     x1="52.006104"
++     y1="166.1331"
++     x2="14.049017"
++     y2="-42.218513" /><linearGradient
++     id="XMLID_39_"
++     gradientUnits="userSpaceOnUse"
++     x1="64.387703"
++     y1="65.124001"
++     x2="64.387703"
++     y2="35.569"
++     gradientTransform="matrix(0.354101,0.000000,0.000000,0.354101,1.638679,-8.364921e-2)">
++                                              <stop
++   offset="0"
++   style="stop-color:#FFFFFF"
++   id="stop336" />
++                                              <stop
++   offset="0.8539"
++   style="stop-color:#FF6200"
++   id="stop338" />
++                                              <stop
++   offset="1"
++   style="stop-color:#F25D00"
++   id="stop340" />
++                                              <midPointStop
++   offset="0"
++   style="stop-color:#FFFFFF"
++   id="midPointStop335" />
++                                              <midPointStop
++   offset="0.5"
++   style="stop-color:#FFFFFF"
++   id="midPointStop337" />
++                                              <midPointStop
++   offset="0.8539"
++   style="stop-color:#FF6200"
++   id="midPointStop339" />
++                                              <midPointStop
++   offset="0.5"
++   style="stop-color:#FF6200"
++   id="midPointStop341" />
++                                              <midPointStop
++   offset="1"
++   style="stop-color:#F25D00"
++   id="midPointStop343" />
++                                      </linearGradient><radialGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient2299"
++     id="radialGradient2305"
++     cx="7.5326638"
++     cy="24.202574"
++     fx="7.5326638"
++     fy="24.202574"
++     r="8.2452128"
++     gradientTransform="matrix(4.100086,-1.627292e-17,2.125447e-14,4.201322,-25.41506,-78.53967)"
++     gradientUnits="userSpaceOnUse" /><radialGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient2307"
++     id="radialGradient2313"
++     cx="19.985598"
++     cy="36.77816"
++     fx="19.985598"
++     fy="36.77816"
++     r="1.0821035"
++     gradientTransform="matrix(1.125263,0.000000,0.000000,0.982744,-3.428678,0.565787)"
++     gradientUnits="userSpaceOnUse" /><radialGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient2319"
++     id="radialGradient2325"
++     cx="20.443665"
++     cy="37.425829"
++     fx="20.443665"
++     fy="37.425829"
++     r="1.0821035"
++     gradientTransform="matrix(1.125263,0.000000,0.000000,0.982744,-3.428678,0.731106)"
++     gradientUnits="userSpaceOnUse" /><linearGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient2329"
++     id="linearGradient2335"
++     x1="17.602522"
++     y1="26.057423"
++     x2="17.682528"
++     y2="32.654099"
++     gradientUnits="userSpaceOnUse"
++     gradientTransform="matrix(0.898789,0,0,1.071914,0.478025,-2.080838)" /><radialGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient2341"
++     id="radialGradient2339"
++     gradientUnits="userSpaceOnUse"
++     gradientTransform="matrix(4.100086,1.627292e-17,2.125447e-14,-4.201322,-5.198109,105.3535)"
++     cx="11.68129"
++     cy="19.554111"
++     fx="11.68129"
++     fy="19.554111"
++     r="8.2452126" /><radialGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient2349"
++     id="radialGradient2355"
++     cx="24.023088"
++     cy="40.56913"
++     fx="24.023088"
++     fy="40.56913"
++     r="16.28684"
++     gradientTransform="matrix(1.000000,0.000000,0.000000,0.431250,1.157278e-15,23.07369)"
++     gradientUnits="userSpaceOnUse" /><radialGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient2368"
++     id="radialGradient2374"
++     cx="29.913452"
++     cy="30.442923"
++     fx="29.913452"
++     fy="30.442923"
++     r="4.0018832"
++     gradientTransform="matrix(3.751495,-2.191984e-22,1.723265e-22,3.147818,-82.00907,-65.70704)"
++     gradientUnits="userSpaceOnUse" /><radialGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient2378"
++     id="radialGradient2384"
++     cx="24.195112"
++     cy="10.577631"
++     fx="24.195112"
++     fy="10.577631"
++     r="15.242914"
++     gradientTransform="matrix(1.125263,-3.585417e-8,4.269819e-8,1.340059,-3.006704,1.355395)"
++     gradientUnits="userSpaceOnUse" /><linearGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient2390"
++     id="linearGradient2396"
++     x1="30.603519"
++     y1="37.337803"
++     x2="30.603519"
++     y2="36.112415"
++     gradientUnits="userSpaceOnUse"
++     gradientTransform="matrix(1.263867,0,0,0.859794,-6.499556,8.390924)" /><linearGradient
++     inkscape:collect="always"
++     xlink:href="#linearGradient2406"
++     id="linearGradient2412"
++     x1="17.850183"
++     y1="28.939463"
++     x2="19.040216"
++     y2="41.03223"
++     gradientUnits="userSpaceOnUse"
++     gradientTransform="matrix(0.888785,0,0,1.08932,2.41099,-1.524336)" /></defs><sodipodi:namedview
++   inkscape:cy="-2.3755359"
++   inkscape:cx="25.234802"
++   inkscape:zoom="1"
++   inkscape:window-height="691"
++   inkscape:window-width="872"
++   inkscape:pageshadow="2"
++   inkscape:pageopacity="0.0"
++   borderopacity="0.21568627"
++   bordercolor="#666666"
++   pagecolor="#ffffff"
++   id="base"
++   inkscape:showpageshadow="false"
++   inkscape:window-x="466"
++   inkscape:window-y="157"
++   inkscape:current-layer="svg2"
++   fill="#555753"
++   showgrid="false"
++   stroke="#a40000"
++   showguides="true"
++   inkscape:guide-bbox="true" />
++      <g
++   style="display:inline"
++   id="g5022"
++   transform="matrix(2.158196e-2,0,0,1.859457e-2,43.12251,41.63767)"><rect
++     y="-150.69685"
++     x="-1559.2523"
++     height="478.35718"
++     width="1339.6335"
++     id="rect4173"
++     style="opacity:0.40206185;color:black;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /><path
++     sodipodi:nodetypes="cccc"
++     id="path5058"
++     d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
++     style="opacity:0.40206185;color:black;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /><path
++     style="opacity:0.40206185;color:black;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++     d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
++     id="path5018"
++     sodipodi:nodetypes="cccc" /></g><path
++   style="color:#000000;fill:url(#linearGradient1514);fill-opacity:1;fill-rule:nonzero;stroke:#757575;stroke-width:1.0000006;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++   d="M 21.619576,8.1833733 L 27.577035,8.1833733 C 28.416767,8.1833733 41.46351,23.618701 41.46351,24.524032 L 41.019989,43.020777 C 41.019989,43.92611 40.343959,44.654954 39.504227,44.654954 L 8.0469496,44.654954 C 7.2072167,44.654954 6.5311871,43.92611 6.5311871,43.020777 L 6.5876651,24.524032 C 6.5876651,23.618701 20.779844,8.1833733 21.619576,8.1833733 z "
++   id="rect1512"
++   sodipodi:nodetypes="ccccccccc" /><path
++   style="fill:none"
++   id="path5"
++   d="M 46.963575,45.735573 L 1.6386762,45.735573 L 1.6386762,0.41067554 L 46.963575,0.41067554 L 46.963575,45.735573 z " /><path
++   style="fill:url(#linearGradient2335);fill-opacity:1;fill-rule:evenodd"
++   id="path2327"
++   d="M 23,29 L 22.954256,44.090942 L 11.111465,44.090942 L 11,29 L 23,29 z "
++   clip-rule="evenodd"
++   sodipodi:nodetypes="ccccc" /><path
++   sodipodi:nodetypes="ccccccccc"
++   id="path2357"
++   d="M 21.780459,9.405584 L 27.339556,9.405584 C 28.123138,9.405584 40.340425,23.805172 40.340425,24.649756 L 39.993267,42.862067 C 39.993267,43.321326 39.84953,43.515532 39.480892,43.515532 L 8.0936894,43.529812 C 7.7250517,43.529812 7.5097258,43.449894 7.5097258,43.076262 L 7.7250676,24.649756 C 7.7250676,23.805172 20.99688,9.405584 21.780459,9.405584 z "
++   style="opacity:0.3125;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /><path
++   clip-rule="evenodd"
++   d="M 7.2075295,27.943053 L 7.1532728,30.538247 L 25.521437,17.358993 L 40.807832,28.513421 L 40.879142,28.201707 L 24.508686,12.297576 L 7.2075295,27.943053 z "
++   id="path23"
++   style="opacity:0.2;fill:url(#radialGradient2384);fill-opacity:1;fill-rule:evenodd"
++   sodipodi:nodetypes="ccccccc" /><path
++   clip-rule="evenodd"
++   d="M 22,30 L 22,44.090942 L 12.188971,44.090942 L 12,30 L 22,30 z "
++   id="path188"
++   style="fill:url(#linearGradient2412);fill-opacity:1;fill-rule:evenodd"
++   sodipodi:nodetypes="ccccc" /><path
++   style="opacity:0.40909089;fill:url(#radialGradient2325);fill-opacity:1;fill-rule:evenodd"
++   id="path2315"
++   d="M 19.576856,36.44767 C 20.249646,36.44767 20.793472,36.922275 20.793472,37.506177 C 20.793472,38.095988 20.249646,38.574532 19.576856,38.574532 C 18.904584,38.574532 18.35817,38.095988 18.35817,37.506177 C 18.358685,36.922275 18.904584,36.44767 19.576856,36.44767 z "
++   clip-rule="evenodd" /><path
++   clip-rule="evenodd"
++   d="M 19.462314,35.932229 C 20.135103,35.932229 20.678929,36.406834 20.678929,36.990736 C 20.678929,37.580545 20.135103,38.059089 19.462314,38.059089 C 18.790041,38.059089 18.243627,37.580545 18.243627,36.990736 C 18.244142,36.406834 18.790041,35.932229 19.462314,35.932229 z "
++   id="path217"
++   style="fill:url(#radialGradient2313);fill-opacity:1;fill-rule:evenodd" /><path
++   d="M 24.447748,11.559337 L 43.374808,28.729205 L 43.869487,29.121196 L 44.273163,28.949811 L 43.900293,28.188138 L 43.622679,27.964702 L 24.447748,12.392396 L 5.0582327,28.135731 L 4.8206309,28.279851 L 4.603921,28.986637 L 5.0373408,29.115885 L 5.4218948,28.807462 L 24.447748,11.559337 z "
++   id="path342"
++   style="fill:url(#XMLID_39_)"
++   sodipodi:nodetypes="ccccccccccccc" /><path
++   style="fill:#ef2929;stroke:#a40000"
++   id="path362"
++   d="M 24.330168,2.2713382 L 2.4484294,20.372675 L 1.8237005,27.538603 L 3.8236367,29.602926 C 3.8236367,29.602926 24.231018,12.445641 24.44773,12.274963 L 44.08027,29.818223 L 45.978694,27.494226 L 44.362903,20.382852 L 24.44773,2.1668788 L 24.330168,2.2713382 z "
++   sodipodi:nodetypes="cccccccccc" />
++<path
++   style="opacity:0.40909089;color:#000000;fill:url(#radialGradient2305);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++   d="M 2.8413446,20.613129 L 2.5497894,27.236494 L 24.369219,8.980075 L 24.298891,3.0867443 L 2.8413446,20.613129 z "
++   id="path1536"
++   sodipodi:nodetypes="ccccc" /><path
++   sodipodi:nodetypes="ccccc"
++   id="path2337"
++   d="M 24.483763,8.7509884 L 24.583223,2.9098867 L 43.912186,20.56184 L 45.403998,27.062652 L 24.483763,8.7509884 z "
++   style="opacity:0.13636367;color:#000000;fill:url(#radialGradient2339);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /><path
++   style="opacity:0.31818183;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.99999934;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++   d="M 27.102228,27.719824 L 36.142223,27.719824 C 36.912818,27.719824 37.53319,28.340194 37.53319,29.110791 L 37.525229,38.190012 C 37.525229,38.960608 36.928907,39.455981 36.158311,39.455981 L 27.102228,39.455981 C 26.331631,39.455981 25.711261,38.835608 25.711261,38.065012 L 25.711261,29.110791 C 25.711261,28.340194 26.331631,27.719824 27.102228,27.719824 z "
++   id="rect2361"
++   sodipodi:nodetypes="ccccccccc" /><rect
++   style="opacity:1;color:#000000;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:#757575;stroke-width:0.9999994;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++   id="rect3263"
++   width="10.001333"
++   height="9.9624557"
++   x="26.507767"
++   y="28.514256"
++   rx="0.38128215"
++   ry="0.38128215" /><path
++   style="opacity:0.39772728;color:#000000;fill:url(#radialGradient2374);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999958;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++   d="M 27.107118,34.408261 C 30.725101,34.739438 32.634842,32.962557 35.97527,32.855521 L 36,29.00603 L 27.088388,29 L 27.107118,34.408261 z "
++   id="rect2363"
++   sodipodi:nodetypes="ccccc" /></svg>
index 0000000,0000000..8270565
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..858cea0
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..7712180
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..b822057
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..4aa9fb5
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..6161343
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,107 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    width: 400; height: 240
++    color: "white"
++
++    ListModel {
++        id: appModel
++        ListElement { name: "Music"; icon: "pics/AudioPlayer_48.png" }
++        ListElement { name: "Movies"; icon: "pics/VideoPlayer_48.png" }
++        ListElement { name: "Camera"; icon: "pics/Camera_48.png" }
++        ListElement { name: "Calendar"; icon: "pics/DateBook_48.png" }
++        ListElement { name: "Messaging"; icon: "pics/EMail_48.png" }
++        ListElement { name: "Todo List"; icon: "pics/TodoList_48.png" }
++        ListElement { name: "Contacts"; icon: "pics/AddressBook_48.png" }
++    }
++
++    Component {
++        id: appDelegate
++        Item {
++            width: 100; height: 100
++            scale: PathView.iconScale
++
++            Image {
++                id: myIcon
++                y: 20; anchors.horizontalCenter: parent.horizontalCenter
++                source: icon
++                smooth: true
++            }
++            Text {
++                anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter }
++                text: name
++                smooth: true
++            }
++
++            MouseArea {
++                anchors.fill: parent
++                onClicked: view.currentIndex = index
++            }
++        }
++    }
++
++    Component {
++        id: appHighlight
++        Rectangle { width: 80; height: 80; color: "lightsteelblue" }
++    }
++
++    PathView {
++        id: view
++        anchors.fill: parent
++        highlight: appHighlight
++        preferredHighlightBegin: 0.5
++        preferredHighlightEnd: 0.5
++        focus: true
++        model: appModel
++        delegate: appDelegate
++        path: Path {
++            startX: 10
++            startY: 50
++            PathAttribute { name: "iconScale"; value: 0.5 }
++            PathQuad { x: 200; y: 150; controlX: 50; controlY: 200 }
++            PathAttribute { name: "iconScale"; value: 1.0 }
++            PathQuad { x: 390; y: 50; controlX: 350; controlY: 200 }
++            PathAttribute { name: "iconScale"; value: 0.5 }
++        }
++    }
++}
index 0000000,0000000..1ab7c8e
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..f4b8689
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..c76b524
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..58f5787
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..d6d84a6
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..0988448
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..52638c5
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..1285931
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,77 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the demonstration applications of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <QGuiApplication>
++#include <QStringList>
++
++#include <qqmlengine.h>
++#include <qqmlcontext.h>
++#include <qqml.h>
++#include <QtQuick/qquickitem.h>
++#include <QtQuick/qquickview.h>
++
++
++/*
++   This example illustrates exposing a QStringList as a
++   model in QML
++*/
++
++int main(int argc, char ** argv)
++{
++    QGuiApplication app(argc, argv);
++
++//![0]
++    QStringList dataList;
++    dataList.append("Item 1");
++    dataList.append("Item 2");
++    dataList.append("Item 3");
++    dataList.append("Item 4");
++
++    QQuickView view;
++    QQmlContext *ctxt = view.rootContext();
++    ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
++//![0]
++
++    view.setSource(QUrl("qrc:view.qml"));
++    view.show();
++
++    return app.exec();
++}
++
index 0000000,0000000..19e62cd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++QT += qml quick
++
++SOURCES += main.cpp 
++RESOURCES += stringlistmodel.qrc
index 0000000,0000000..17e9301
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++<!DOCTYPE RCC><RCC version="1.0">
++<qresource>
++    <file>view.qml</file>
++</qresource>
++</RCC>
index 0000000,0000000..945763c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,54 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++//![0]
++
++ListView {
++    width: 100; height: 100
++
++    model: myModel
++    delegate: Rectangle {
++        height: 25
++        width: 100
++        Text { text: modelData }
++    }
++}
++//![0]
index 0000000,0000000..c3186a5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,200 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    id: root
++
++    width: 320
++    height: 480
++
++    property bool dragging: false
++
++    Component {
++        id: packageDelegate
++        Package {
++            id: packageRoot
++
++            MouseArea {
++                id: visibleContainer
++                Package.name: "visible"
++
++                width: 64
++                height: 64
++                enabled: packageRoot.VisualDataModel.inSelected
++
++                drag.target: draggable
++
++                Item {
++                    id: draggable
++
++                    width: 64
++                    height: 64
++
++                    Drag.active: visibleContainer.drag.active
++
++                    anchors { horizontalCenter: parent.horizontalCenter; verticalCenter: parent.verticalCenter }
++
++                    states: State {
++                        when: visibleContainer.drag.active
++                        AnchorChanges { target:  draggable; anchors { horizontalCenter: undefined; verticalCenter: undefined} }
++                        ParentChange { target: selectionView; parent: draggable; x: 0; y: 0 }
++                        PropertyChanges { target: root; dragging: true }
++                        ParentChange { target: draggable; parent: root }
++                    }
++                }
++                DropArea {
++                    anchors.fill: parent
++                    onEntered: selectedItems.move(0, visualModel.items.get(packageRoot.VisualDataModel.itemsIndex), selectedItems.count)
++                }
++            }
++            Item {
++                id: selectionContainer
++                Package.name: "selection"
++
++                width: 64
++                height: 64
++
++                visible: PathView.onPath
++            }
++            Rectangle {
++                id: content
++                parent: visibleContainer
++
++                width: 58
++                height: 58
++
++                radius: 8
++
++                gradient: Gradient {
++                    GradientStop { id: gradientStart; position: 0.0; color: "#8AC953" }
++                    GradientStop { id: gradientEnd; position: 1.0; color: "#8BC953" }
++                }
++
++                border.width: 2
++                border.color: "#007423"
++
++                state: root.dragging && packageRoot.VisualDataModel.inSelected ? "selected" : "visible"
++
++                Text {
++                    anchors.fill: parent
++                    horizontalAlignment: Text.AlignHCenter
++                    verticalAlignment: Text.AlignVCenter
++                    color: "white"
++                    text: modelData
++                    font.pixelSize: 18
++                }
++
++                Rectangle {
++                    anchors { right: parent.right; top: parent.top; margins: 3 }
++                    width: 12; height: 12
++                    color: packageRoot.VisualDataModel.inSelected ? "black" : "white"
++                    radius: 6
++
++                    border.color: "white"
++                    border.width: 2
++
++                    MouseArea {
++                        anchors.fill: parent
++                        onClicked: packageRoot.VisualDataModel.inSelected = !packageRoot.VisualDataModel.inSelected
++                    }
++                }
++
++                states: [
++                    State {
++                        name: "selected"
++                        ParentChange { target: content; parent: selectionContainer; x: 3; y: 3 }
++                        PropertyChanges { target: packageRoot; VisualDataModel.inItems: visibleContainer.drag.active }
++                        PropertyChanges { target: gradientStart; color: "#017423" }
++                        PropertyChanges { target: gradientStart; color: "#007423" }
++                    }, State {
++                        name: "visible"
++                        PropertyChanges { target: packageRoot; VisualDataModel.inItems: true }
++                        ParentChange { target: content; parent: visibleContainer; x: 3; y: 3 }
++                        PropertyChanges { target: gradientStart; color: "#8AC953" }
++                        PropertyChanges { target: gradientStart; color: "#8BC953" }
++                    }
++                ]
++                transitions: Transition {
++                    PropertyAction { target: packageRoot; properties: "VisualDataModel.inItems" }
++                    ParentAnimation {
++                        target: content
++                        NumberAnimation { target: content; properties: "x,y"; duration: 500 }
++                    }
++                    ColorAnimation { targets: [gradientStart, gradientEnd]; duration: 500 }
++                }
++            }
++        }
++    }
++
++    VisualDataModel {
++        id: visualModel
++        model: 35
++        delegate: packageDelegate
++
++        groups: VisualDataGroup { id: selectedItems; name: "selected" }
++
++        Component.onCompleted:  parts.selection.filterOnGroup = "selected"
++    }
++
++    PathView {
++        id: selectionView
++
++        height: 64
++        width: 64
++
++        model: visualModel.parts.selection
++
++        path: Path {
++            startX: 0
++            startY: 0
++            PathLine { x: 64; y: 64 }
++        }
++    }
++
++    GridView {
++        id: itemsView
++        anchors { fill: parent }
++        cellWidth: 64
++        cellHeight: 64
++        model: visualModel.parts.visible
++    }
++}
index 0000000,0000000..040c6be
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,156 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import QtQuick.XmlListModel 2.0
++
++Rectangle {
++    id: root
++
++    property Item displayItem: null
++
++    width: 300; height: 400
++
++    color: "black"
++
++    VisualDataModel {
++        id: visualModel
++
++        model: XmlListModel {
++            source: "http://api.flickr.com/services/feeds/photos_public.gne?format=rss2"
++            query: "/rss/channel/item"
++            namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
++
++            XmlRole { name: "imagePath"; query: "media:thumbnail/@url/string()" }
++            XmlRole { name: "url"; query: "media:content/@url/string()" }
++        }
++
++        delegate: Item {
++            id: delegateItem
++
++            width: 76; height: 76
++
++            Rectangle {
++                id: image
++                x: 0; y: 0; width: 76; height: 76
++                border.width: 1
++                border.color: "white"
++                color: "black"
++
++                Image {
++                    anchors.fill: parent
++                    anchors.leftMargin: 1
++                    anchors.topMargin: 1
++
++                    source: imagePath
++                    fillMode: Image.PreserveAspectFit
++
++                }
++
++                MouseArea {
++                    id: clickArea
++                    anchors.fill: parent
++
++                    onClicked: root.displayItem = root.displayItem !== delegateItem ? delegateItem : null
++                }
++
++                states: [
++                    State {
++                        when: root.displayItem === delegateItem
++                        name: "inDisplay";
++                        ParentChange { target: image; parent: imageContainer; x: 75; y: 75; width: 150; height: 150 }
++                        PropertyChanges { target: image; z: 2 }
++                        PropertyChanges { target: delegateItem; VisualDataModel.inItems: false }
++                    },
++                    State {
++                        when: root.displayItem !== delegateItem
++                        name: "inList";
++                        ParentChange { target: image; parent: delegateItem; x: 2; y: 2; width: 75; height: 75 }
++                        PropertyChanges { target: image; z: 1 }
++                        PropertyChanges { target: delegateItem; VisualDataModel.inItems: true }
++                    }
++                ]
++
++                transitions: [
++                    Transition {
++                        from: "inList"
++                        SequentialAnimation {
++                            PropertyAction { target: delegateItem; property: "VisualDataModel.inPersistedItems"; value: true }
++                            ParentAnimation {
++                                target: image;
++                                via: root
++                                NumberAnimation { target: image; properties: "x,y,width,height"; duration: 1000 }
++                            }
++                        }
++                    }, Transition {
++                        from: "inDisplay"
++                        SequentialAnimation {
++                            ParentAnimation {
++                                target: image
++                                NumberAnimation { target: image; properties: "x,y,width,height"; duration: 1000 }
++                            }
++                            PropertyAction { target: delegateItem; property: "VisualDataModel.inPersistedItems"; value: false }
++                        }
++                    }
++                ]
++            }
++        }
++    }
++
++
++    PathView {
++        id: imagePath
++
++        anchors { left: parent.left; top: imageContainer.bottom; right: parent.right; bottom: parent.bottom }
++        model: visualModel
++
++        pathItemCount: 7
++        path: Path {
++            startX: -50; startY: 0
++            PathQuad { x: 150; y: 50; controlX: 0; controlY: 50 }
++            PathQuad { x: 350; y: 0; controlX: 300; controlY: 50 }
++        }
++    }
++
++    Item {
++        id: imageContainer
++        anchors { fill: parent; bottomMargin: 100 }
++    }
++}
index 0000000,0000000..8d3b0a5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,141 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    width: 480; height: 640
++
++    Component {
++        id: numberDelegate
++
++        Text {
++            id: numberText
++            anchors { left: parent.left; right: parent.right }
++            text: number
++
++            horizontalAlignment: Text.AlignHCenter
++            font.pixelSize: 18
++
++            Text {
++                anchors { left: parent.left; baseline: parent.baseline }
++                text: index
++
++                horizontalAlignment: Text.AlignLeft
++                font.pixelSize: 12
++            }
++            Text {
++                anchors { right: parent.right; baseline: parent.baseline }
++                text: numberText.VisualDataModel.itemsIndex
++
++                horizontalAlignment: Text.AlignRight
++                font.pixelSize: 12
++            }
++        }
++    }
++
++    ListView {
++        anchors {
++            left: parent.left; top: parent.top;
++            right: parent.horizontalCenter; bottom: button.top
++            leftMargin: 2; topMargin: 2; rightMargin: 1; bottomMargin: 2
++        }
++
++        model: ListModel {
++            id: unsortedModel
++        }
++        delegate: numberDelegate
++    }
++    ListView {
++        anchors {
++            left: parent.horizontalCenter; top: parent.top;
++            right: parent.right; bottom: button.top
++            leftMargin: 1; topMargin: 2; rightMargin: 2; bottomMargin: 2
++        }
++        model: VisualDataModel {
++            model: unsortedModel
++            delegate: numberDelegate
++
++            items.onChanged: {
++                for (var i = 0; i < inserted.length; ++i) {
++                    for (var j = inserted[i].index; j < inserted[i].index + inserted[i].count; ++j) {
++                        var number = items.get(j).model.number
++                        for (var l = 0, k = 0; l < unsortedModel.count; ++l) {
++                            if (l == inserted[k].index) {
++                                l += inserted[k].count - 1
++                                ++k
++                            } else if (number < items.get(l).model.number) {
++                                items.move(j, l, 1)
++                                break
++                            }
++                        }
++                        inserted[i].index += 1;
++                        inserted[i].count -= 1;
++                    }
++                }
++            }
++        }
++    }
++
++    Rectangle {
++        id: button
++
++        anchors { left: parent.left; right: parent.right; bottom: parent.bottom; margins: 2 }
++        height: moreText.implicitHeight + 4
++
++        color: "black"
++
++        Text {
++            id: moreText
++
++            anchors.fill: parent
++            text: "More"
++            color: "white"
++            font.pixelSize: 18
++            horizontalAlignment: Text.AlignHCenter
++            verticalAlignment: Text.AlignVCenter
++        }
++        MouseArea {
++            anchors.fill: parent
++
++            onClicked: unsortedModel.append({ "number": Math.floor(Math.random() * 100) })
++        }
++    }
++}
index 0000000,0000000..2bb4016
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,14 @@@
++import QmlProject 1.0
++
++Project {
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..30e3e62
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,176 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: box
++    width: 400; height: 300
++
++    Rectangle {
++        id: redSquare
++        width: 120; height: 120
++        anchors.top: parent.top; anchors.left: parent.left; anchors.margins: 10
++        color: "red"
++
++        Text { text: "Click"; font.pixelSize: 16; anchors.centerIn: parent }
++
++        MouseArea {
++            anchors.fill: parent
++            hoverEnabled: true
++            property string buttonID
++
++            acceptedButtons: Qt.AllButtons
++            // Value 'All.Buttons' is eqivalent to:
++            // 'Qt::LeftButton | Qt::RightButton | Qt::MiddleButton  .... | Qt::ExtraButton24'
++
++            onEntered: info.text = 'Entered'
++            onExited: info.text = 'Exited (pressed=' + pressed + ')'
++
++            onPressed: {
++                if (mouse.button == Qt.LeftButton)
++                    buttonID = 'LeftButton'
++                else if (mouse.button == Qt.RightButton)
++                    buttonID = 'RightButton'
++                else if (mouse.button == Qt.MidButton)
++                    buttonID = 'MiddleButton'
++                else if (mouse.button == Qt.BackButton)
++                    buttonID = 'BackButton'
++                else if (mouse.button == Qt.ForwardButton)
++                    buttonID = 'ForwardButton'
++                else if (mouse.button == Qt.TaskButton)
++                    buttonID = 'TaskButton'
++                else if (mouse.button == Qt.ExtraButton4)
++                    buttonID = 'ExtraButton4'
++                else if (mouse.button == Qt.ExtraButton5)
++                    buttonID = 'ExtraButton5'
++                else if (mouse.button == Qt.ExtraButton6)
++                    buttonID = 'ExtraButton6'
++                else if (mouse.button == Qt.ExtraButton7)
++                    buttonID = 'ExtraButton7'
++                else if (mouse.button == Qt.ExtraButton8)
++                    buttonID = 'ExtraButton8'
++                else if (mouse.button == Qt.ExtraButton9)
++                    buttonID = 'ExtraButton9'
++                else if (mouse.button == Qt.ExtraButton10)
++                    buttonID = 'ExtraButton10'
++                else if (mouse.button == Qt.ExtraButton11)
++                    buttonID = 'ExtraButton11'
++                else if (mouse.button == Qt.ExtraButton12)
++                    buttonID = 'ExtraButton12'
++                else if (mouse.button == Qt.ExtraButton13)
++                    buttonID = 'ExtraButton13'
++                else if (mouse.button == Qt.ExtraButton14)
++                    buttonID = 'ExtraButton14'
++                else if (mouse.button == Qt.ExtraButton15)
++                    buttonID = 'ExtraButton15'
++                else if (mouse.button == Qt.ExtraButton16)
++                    buttonID = 'ExtraButton16'
++                else if (mouse.button == Qt.ExtraButton17)
++                    buttonID = 'ExtraButton17'
++                else if (mouse.button == Qt.ExtraButton18)
++                    buttonID = 'ExtraButton18'
++                else if (mouse.button == Qt.ExtraButton19)
++                    buttonID = 'ExtraButton19'
++                else if (mouse.button == Qt.ExtraButton20)
++                    buttonID = 'ExtraButton20'
++                else if (mouse.button == Qt.ExtraButton21)
++                    buttonID = 'ExtraButton21'
++                else if (mouse.button == Qt.ExtraButton22)
++                    buttonID = 'ExtraButton22'
++                else if (mouse.button == Qt.ExtraButton23)
++                    buttonID = 'ExtraButton23'
++                else if (mouse.button == Qt.ExtraButton24)
++                    buttonID = 'ExtraButton24'
++
++                info.text = 'Pressed (' + buttonID + ' shift='
++                    + (mouse.modifiers & Qt.ShiftModifier ? 'true' : 'false') + ')'
++                var posInBox = redSquare.mapToItem(box, mouse.x, mouse.y)
++                posInfo.text = + mouse.x + ',' + mouse.y + ' in square'
++                        + ' (' + posInBox.x + ',' + posInBox.y + ' in window)'
++            }
++
++            onReleased: {
++                btn.text = 'Released (isClick=' + mouse.isClick + ' wasHeld=' + mouse.wasHeld + ')'
++                posInfo.text = ''
++            }
++
++            onPressAndHold: btn.text = 'Press and hold'
++            onClicked: btn.text = 'Clicked (wasHeld=' + mouse.wasHeld + ')'
++            onDoubleClicked: btn.text = 'Double clicked'
++        }
++    }
++
++    Rectangle {
++        id: blueSquare
++        width: 120; height: 120
++        x: box.width - width - 10; y: 10    // making this item draggable, so don't use anchors
++        color: "blue"
++
++        Text { text: "Drag"; font.pixelSize: 16; color: "white"; anchors.centerIn: parent }
++
++        MouseArea {
++            anchors.fill: parent
++            drag.target: blueSquare
++            drag.axis: Drag.XandYAxis
++            drag.minimumX: 0
++            drag.maximumX: box.width - parent.width
++            drag.minimumY: 0
++            drag.maximumY: box.height - parent.width
++        }
++    }
++
++    Text {
++        id: info
++        anchors.bottom: btn.top; anchors.horizontalCenter: parent.horizontalCenter; anchors.margins: 20
++
++        onTextChanged: console.log(text)
++    }
++
++    Text {
++        id: btn
++        anchors.bottom: posInfo.top; anchors.horizontalCenter: parent.horizontalCenter; anchors.margins: 20
++    }
++
++    Text {
++        id: posInfo
++        anchors.bottom: parent.bottom; anchors.horizontalCenter: parent.horizontalCenter; anchors.margins: 20
++    }
++}
index 0000000,0000000..3b682de
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,60 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the demonstration applications of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <QGuiApplication>
++
++#include <QtQuick/QQuickView>
++
++#include "squircle.h"
++
++int main(int argc, char **argv)
++{
++    QGuiApplication app(argc, argv);
++
++    qmlRegisterType<Squircle>("QtQuick", 2, 0, "Squircle");
++
++    QQuickView view;
++    view.setSource(QUrl("main.qml"));
++    view.show();
++
++    return app.exec();
++
++}
index 0000000,0000000..1485cbb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,78 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the demonstration applications of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++
++    width: 400
++    height: 300
++
++    Squircle {
++        SequentialAnimation on t {
++            NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad }
++            NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad }
++            loops: Animation.Infinite
++            running: true
++        }
++    }
++
++    Rectangle {
++        color: Qt.rgba(1, 1, 1, 0.8);
++        radius: 10
++        border.width: 1
++        border.color: "white"
++        anchors.fill: label
++        anchors.margins: -10
++    }
++
++    Text {
++        id: label
++        color: "black"
++        wrapMode: Text.WordWrap
++        text: "The background here is a squircle rendered with raw OpenGL using the 'beforeRender()' signal in QQuickCanvas. This text label and its border is rendered using QML"
++        anchors.right: parent.right
++        anchors.left: parent.left
++        anchors.bottom: parent.bottom
++        anchors.margins: 20
++    }
++
++}
index 0000000,0000000..64a58b3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,6 @@@
++QT += qml quick
++
++HEADERS += squircle.h
++SOURCES += squircle.cpp main.cpp
++
++OTHER_FILES += main.qml
index 0000000,0000000..b56f0ba
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,123 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the demonstration applications of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include "squircle.h"
++
++#include <QtQuick/qsgengine.h>
++#include <QtQuick/qquickcanvas.h>
++#include <QOpenGLShaderProgram>
++
++Squircle::Squircle()
++    : m_program(0)
++{
++    setFlag(ItemHasContents);
++}
++
++void Squircle::itemChange(ItemChange change, const ItemChangeData &)
++{
++    // The ItemSceneChange event is sent when we are first attached to a canvas.
++    if (change == ItemSceneChange) {
++        QQuickCanvas *c = canvas();
++
++        // Connect our the beforeRendering signal to our paint function.
++        // Since this call is executed on the rendering thread it must be
++        // a Qt::DirectConnection
++        connect(c, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection);
++
++        // If we allow QML to do the clearing, they would clear what we paint
++        // and nothing would show.
++        c->setClearBeforeRendering(false);
++    }
++}
++
++
++void Squircle::paint()
++{
++    if (!m_program) {
++        m_program = new QOpenGLShaderProgram();
++        m_program->addShaderFromSourceCode(QOpenGLShader::Vertex,
++                                           "attribute highp vec4 vertices;"
++                                           "varying highp vec2 coords;"
++                                           "void main() {"
++                                           "    gl_Position = vertices;"
++                                           "    coords = vertices.xy;"
++                                           "}");
++        m_program->addShaderFromSourceCode(QOpenGLShader::Fragment,
++                                           "uniform lowp float t;"
++                                           "varying highp vec2 coords;"
++                                           "void main() {"
++                                           "    lowp float i = 1. - (pow(coords.x, 4.) + pow(coords.y, 4.));"
++                                           "    i = smoothstep(t - 0.3, t + 0.3, i);"
++                                           "    gl_FragColor = vec4(coords / 2. + .5, i, i);"
++                                           "}");
++
++        m_program->bindAttributeLocation("vertices", 0);
++        m_program->link();
++    }
++
++    m_program->bind();
++
++    m_program->enableAttributeArray(0);
++
++    float values[] = {
++        -1, -1,
++        1, -1,
++        -1, 1,
++        1, 1
++    };
++    m_program->setAttributeArray(0, GL_FLOAT, values, 2);
++    m_program->setUniformValue("t", (float) m_t);
++
++    glDisable(GL_DEPTH_TEST);
++
++    glClearColor(0, 0, 0, 1);
++    glClear(GL_COLOR_BUFFER_BIT);
++
++    glEnable(GL_BLEND);
++    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
++
++    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
++
++    m_program->disableAttributeArray(0);
++    m_program->release();
++}
++
++
index 0000000,0000000..283131a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,76 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the demonstration applications of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#ifndef SQUIRCLE_H
++#define SQUIRCLE_H
++
++#include <QtQuick/QQuickItem>
++#include <QtGui/QOpenGLShaderProgram>
++
++class Squircle : public QQuickItem
++{
++    Q_OBJECT
++
++    Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged)
++
++public:
++    Squircle();
++
++    qreal t() const { return m_t; }
++    void setT(qreal t) { m_t = t; emit tChanged(); }
++
++    void itemChange(ItemChange change, const ItemChangeData &);
++
++signals:
++    void tChanged();
++
++public slots:
++    void paint();
++
++private:
++    QOpenGLShaderProgram *m_program;
++
++    qreal m_t;
++    bool m_render_under;
++    bool m_render_over;
++};
++
++#endif // SQUIRCLE_H
index 0000000,0000000..e3afd6b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++TEMPLATE = subdirs
++
++SUBDIRS = \
++    smile \
++    textballoons
index 0000000,0000000..1c7888b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,96 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <QGuiApplication>
++#include <QPainter>
++#include <QtQml/qqml.h>
++#include <QtQuick/qquickview.h>
++#include <QtQuick/qquickpainteditem.h>
++class MyPaintItem : public QQuickPaintedItem
++{
++    Q_OBJECT
++    Q_PROPERTY(QString face READ face WRITE setFace NOTIFY faceChanged)
++public:
++    MyPaintItem()
++      : QQuickPaintedItem()
++      , m_face(QLatin1String(":-)"))
++    {
++        setAntialiasing(true);
++    }
++    QString face() const {return m_face;}
++    void setFace(const QString &face) {
++       if (m_face != face) {
++          m_face = face;
++          emit faceChanged();
++       }
++    }
++    virtual void paint(QPainter *p)
++    {
++        QRectF rect(0, 0, width(), height());
++        rect.adjust(10, 10, -10, -10);
++        p->setPen(QPen(Qt::black, 20));
++        p->setBrush(Qt::yellow);
++        p->drawEllipse(rect);
++        p->setPen(Qt::black);
++        p->setFont(QFont(QLatin1String("Times"), qRound(rect.height() / 2)));
++        p->drawText(rect, Qt::AlignCenter, m_face);
++    }
++signals:
++    void faceChanged();
++private:
++    QString m_face;
++};
++
++int main(int argc, char ** argv)
++{
++    QGuiApplication app(argc, argv);
++
++    qmlRegisterType<MyPaintItem>("MyModule", 1, 0, "MyPaintItem");
++
++    QQuickView view;
++    view.setResizeMode(QQuickView::SizeRootObjectToView);
++    view.setSource(QUrl::fromLocalFile("smile.qml"));
++    view.show();
++    view.raise();
++
++    return app.exec();
++}
++
++#include "main.moc"
index 0000000,0000000..b1af4ee
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,11 @@@
++TEMPLATE = app
++TARGET = painteditem
++
++QT += qml quick
++
++macx: CONFIG -= app_bundle
++
++SOURCES += main.cpp
++
++CONFIG += console
++
index 0000000,0000000..33919bc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,132 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import MyModule 1.0
++
++Rectangle {
++    width: 500
++    height: 500
++    gradient: Gradient {
++        GradientStop { position: 0.0; color: "#00249a" }
++        GradientStop { position: 0.7; color: "#ffd94f" }
++        GradientStop { position: 1.0; color: "#ffa322" }
++    }
++    MyPaintItem {
++        renderTarget:PaintedItem.Image
++        clip:true
++        width:240
++        height:240
++        anchors.left : parent.left
++        anchors.top :parent.top
++        anchors.margins: 10
++        smooth: true
++        MouseArea {
++          anchors.fill:parent
++          onClicked: {
++           if (parent.face == ":-)")
++              parent.face = ":-(";
++           else
++              parent.face = ":-)";
++           parent.update()
++          }
++        }
++    }
++    MyPaintItem {
++        clip:true
++        renderTarget:PaintedItem.Image
++        width:240
++        height:240
++        anchors.right : parent.right
++        anchors.top :parent.top
++        anchors.margins: 10
++        smooth: true
++        MouseArea {
++          anchors.fill:parent
++          onClicked: {
++           if (parent.face == ":-)")
++              parent.face = ":-(";
++           else
++              parent.face = ":-)";
++           parent.update()
++          }
++        }
++    }
++    MyPaintItem {
++        clip:true
++        renderTarget:PaintedItem.Image
++        width:240
++        height:240
++        anchors.left : parent.left
++        anchors.bottom :parent.bottom
++        anchors.margins: 10
++        smooth: true
++        MouseArea {
++          anchors.fill:parent
++          onClicked: {
++           if (parent.face == ":-)")
++              parent.face = ":-(";
++           else
++              parent.face = ":-)";
++           parent.update()
++          }
++        }
++    }
++    MyPaintItem {
++        clip:true
++        renderTarget:PaintedItem.Image
++        width:240
++        height:240
++        anchors.right : parent.right
++        anchors.bottom :parent.bottom
++        anchors.margins: 10
++        smooth: true
++        MouseArea {
++          anchors.fill:parent
++          onClicked: {
++           if (parent.face == ":-)")
++              parent.face = ":-(";
++           else
++              parent.face = ":-)";
++           parent.update()
++          }
++        }
++    }
++}
index 0000000,0000000..c500c1c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,55 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the demonstration applications of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <QQmlExtensionPlugin>
++
++#include "../textballoon.h"
++
++class TextBalloonPlugin : public QQmlExtensionPlugin
++{
++    Q_OBJECT
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "textballoon.json")
++public:
++    void registerTypes(const char *uri)
++    {
++        qmlRegisterType<TextBalloon>(uri, 1, 0, "TextBalloon");
++    }
++};
index 0000000,0000000..e8a08ae
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1 @@@
++plugin qmltextballoonplugin
index 0000000,0000000..d097adf
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,92 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the demonstration applications of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include "textballoon.h"
++
++//! [0]
++TextBalloon::TextBalloon(QQuickItem *parent)
++    : QQuickPaintedItem(parent)
++    , rightAligned(false)
++{
++}
++//! [0]
++
++//! [1]
++void TextBalloon::paint(QPainter *painter)
++{
++    QBrush brush(QColor("#007430"));
++
++    painter->setBrush(brush);
++    painter->setPen(Qt::NoPen);
++    painter->setRenderHint(QPainter::Antialiasing);
++
++    painter->drawRoundedRect(0, 0, boundingRect().width(), boundingRect().height() - 10, 10, 10);
++
++    if (rightAligned)
++    {
++        const QPointF points[3] = {
++            QPointF(boundingRect().width() - 10.0, boundingRect().height() - 10.0),
++            QPointF(boundingRect().width() - 20.0, boundingRect().height()),
++            QPointF(boundingRect().width() - 30.0, boundingRect().height() - 10.0),
++        };
++        painter->drawConvexPolygon(points, 3);
++    }
++    else
++    {
++        const QPointF points[3] = {
++            QPointF(10.0, boundingRect().height() - 10.0),
++            QPointF(20.0, boundingRect().height()),
++            QPointF(30.0, boundingRect().height() - 10.0),
++        };
++        painter->drawConvexPolygon(points, 3);
++    }
++}
++//! [1]
++
++bool TextBalloon::isRightAligned()
++{
++    return this->rightAligned;
++}
++
++void TextBalloon::setRightAligned(bool rightAligned)
++{
++    this->rightAligned = rightAligned;
++}
index 0000000,0000000..93ed0a7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,68 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the demonstration applications of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#ifndef TEXTBALLOON_H
++#define TEXTBALLOON_H
++
++#include <QtQuick>
++
++//! [0]
++class TextBalloon : public QQuickPaintedItem
++{
++    Q_OBJECT
++    Q_PROPERTY(bool rightAligned READ isRightAligned WRITE setRightAligned NOTIFY rightAlignedChanged)
++
++    public:
++        TextBalloon(QQuickItem *parent = 0);
++        void paint(QPainter *painter);
++
++        bool isRightAligned();
++        void setRightAligned(bool rightAligned);
++
++    private:
++        bool rightAligned;
++
++    signals:
++        void rightAlignedChanged();
++};
++//! [0]
++
++#endif
index 0000000,0000000..d612048
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,25 @@@
++TEMPLATE = lib
++CONFIG += qt plugin
++QT += qml quick
++
++TARGET = qmltextballoonplugin
++
++HEADERS += TextBalloonPlugin/plugin.h \
++    textballoon.h
++
++SOURCES += textballoon.cpp
++
++OTHER_FILES += textballoon.json
++
++DESTDIR = TextBalloonPlugin
++
++qdeclarativesources.files += \
++    TextBalloonPlugin/qmldir
++
++qdeclarativesources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/painteditem/textballoons/TextBalloonPlugin
++ 
++sources.files = textballoons.qml
++sources.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/painteditem/textballoons
++target.path += $$[QT_INSTALL_EXAMPLES]/qtdeclarative/qml/painteditem/textballoons/TextBalloonPlugin
++
++INSTALLS = qdeclarativesources sources target
index 0000000,0000000..b00ce2b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,110 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the demonstration applications of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import TextBalloonPlugin 1.0
++
++Item {
++    height: 480
++    width: 640
++
++    //! [0]
++    ListModel {
++        id: balloonModel
++        ListElement {
++            balloonWidth: 200
++        }
++        ListElement {
++            balloonWidth: 350
++        }
++    }
++
++    ListView {
++        anchors.bottom: controls.top
++        anchors.bottomMargin: 2
++        anchors.top: parent.top
++        id: balloonView
++        delegate: TextBalloon {
++            anchors.right: index % 2 == 0 ? undefined : parent.right
++            height: 60
++            rightAligned: index % 2 == 0 ? false : true
++            width: balloonWidth
++        }
++        model: balloonModel
++        spacing: 5
++        width: parent.width
++    }
++    //! [0]
++
++    //! [1]
++    Rectangle {
++        id: controls
++ 
++        anchors.bottom: parent.bottom
++        anchors.left: parent.left
++        anchors.margins: 1
++        anchors.right: parent.right
++        border.width: 2
++        color: "white"
++        height: parent.height * 0.15
++
++        Text {
++            anchors.centerIn: parent
++            text: "Add another balloon"
++        }
++
++        MouseArea {
++            anchors.fill: parent
++            hoverEnabled: true
++            onClicked: {
++                balloonModel.append({"balloonWidth": Math.floor(Math.random() * 300 + 100)})
++                balloonView.positionViewAtIndex(balloonView.count -1, ListView.End)
++            }
++            onEntered: {
++                parent.color = "#8ac953"
++            }
++            onExited: {
++                parent.color = "white"
++            }
++        }
++    }
++    //! [1]
++}
index 0000000,0000000..ee3aa90
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,78 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: page
++
++    property string text
++    property string icon
++    signal clicked
++
++    border.color: "black"; color: "steelblue"; radius: 5
++    width: pix.width + textelement.width + 13
++    height: pix.height + 10
++
++    Image { id: pix; x: 5; y:5; source: parent.icon }
++
++    Text {
++        id: textelement
++        text: page.text; color: "white"
++        x: pix.width + pix.x + 3
++        anchors.verticalCenter: pix.verticalCenter
++    }
++
++    MouseArea {
++        id: mr
++        anchors.fill: parent
++        onClicked: { parent.focus = true; page.clicked() }
++    }
++
++    states: State {
++        name: "pressed"; when: mr.pressed
++        PropertyChanges { target: textelement; x: 5 }
++        PropertyChanges { target: pix; x: textelement.x + textelement.width + 3 }
++    }
++
++    transitions: Transition {
++        NumberAnimation { properties: "x,left"; easing.type: Easing.InOutQuad; duration: 200 }
++    }
++}
index 0000000,0000000..1ee4542
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..8d2eaed
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..a05927f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,106 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++  width: 400
++  height: 100
++
++  // Create row with four rectangles, the fourth one is hidden
++  Row {
++    id: row
++
++    Rectangle {
++      id: red
++      color: "red"
++      width: 100
++      height: 100
++
++      // When mouse is clicked, display the values of the positioner
++      MouseArea {
++        anchors.fill: parent
++        onClicked: row.showInfo(red.Positioner)
++      }
++    }
++
++    Rectangle {
++      id: green
++      color: "green"
++      width: 100
++      height: 100
++
++      // When mouse is clicked, display the values of the positioner
++      MouseArea {
++        anchors.fill: parent
++        onClicked: row.showInfo(green.Positioner)
++      }
++    }
++
++    Rectangle {
++      id: blue
++      color: "blue"
++      width: 100
++      height: 100
++
++      // When mouse is clicked, display the values of the positioner
++      MouseArea {
++        anchors.fill: parent
++        onClicked: row.showInfo(blue.Positioner)
++      }
++    }
++
++    // This rectangle is not visible, so it doesn't have a positioner value
++    Rectangle {
++      color: "black"
++      width: 100
++      height: 100
++      visible: false
++    }
++
++    // Print the index of the child item in the positioner and convenience
++    // properties showing if it's the first or last item.
++    function showInfo(positioner) {
++      console.log("Item Index = " + positioner.index)
++      console.log("  isFirstItem = " + positioner.isFirstItem)
++      console.log("  isLastItem = " + positioner.isLastItem)
++    }
++  }
++}
index 0000000,529f65a..529f65a
mode 000000,100644..100644
--- /dev/null
index 0000000,0000000..0c65647
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,246 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: root
++    property bool mirror
++    property int direction: Qt.application.layoutDirection
++    LayoutMirroring.enabled: mirror
++    LayoutMirroring.childrenInherit: true
++    width: column.width + 80
++    height: column.height + 40
++    Column {
++        id: column
++        width: 190
++        spacing: 10
++        anchors.centerIn: parent
++
++        Text {
++            text: "Row"
++            anchors.horizontalCenter: parent.horizontalCenter
++        }
++
++        Row {
++            layoutDirection: root.direction
++            spacing: 10
++            move: Transition {
++                NumberAnimation {
++                    properties: "x"
++                }
++            }
++            Repeater {
++                model: 4
++                Loader {
++                    property int value: index
++                    sourceComponent: positionerDelegate
++                }
++            }
++        }
++
++        Text {
++            text: "Grid"
++            anchors.horizontalCenter: parent.horizontalCenter
++        }
++
++        Grid {
++            layoutDirection: root.direction
++            spacing: 10; columns: 4
++            move: Transition {
++                NumberAnimation {
++                    properties: "x"
++                }
++            }
++            Repeater {
++                model: 11
++                Loader {
++                    property int value: index
++                    sourceComponent: positionerDelegate
++                }
++            }
++        }
++
++        Text {
++            text: "Flow"
++            anchors.horizontalCenter: parent.horizontalCenter
++        }
++
++        Flow {
++            layoutDirection: root.direction
++            spacing: 10; width: parent.width
++            move: Transition {
++                NumberAnimation {
++                    properties: "x"
++                }
++            }
++            Repeater {
++                model: 10
++                Loader {
++                    property int value: index
++                    sourceComponent: positionerDelegate
++                }
++            }
++        }
++
++        Text {
++            text: "ListView"
++            anchors.horizontalCenter: parent.horizontalCenter
++        }
++
++        ListView {
++            id: listView
++            clip: true
++            width: parent.width; height: 40
++            layoutDirection: root.direction
++            orientation: Qt.Horizontal
++            model: 48
++            delegate: viewDelegate
++        }
++
++        Text {
++            text: "GridView"
++            anchors.horizontalCenter: parent.horizontalCenter
++        }
++
++        GridView {
++            clip: true
++            width: 200; height: 160
++            cellWidth: 50; cellHeight: 50
++            layoutDirection: root.direction
++            model: 48
++            delegate: viewDelegate
++        }
++
++        Rectangle {
++            height: 50; width: parent.width
++            color: mouseArea.pressed ? "black" : "gray"
++            Column {
++                anchors.centerIn: parent
++                Text {
++                    text: root.direction ? "Right to left" : "Left to right"
++                    color: "white"
++                    font.pixelSize: 16
++                    anchors.horizontalCenter: parent.horizontalCenter
++                }
++                Text {
++                    text: "(click here to toggle)"
++                    color: "white"
++                    font.pixelSize: 10
++                    font.italic: true
++                    anchors.horizontalCenter: parent.horizontalCenter
++                }
++            }
++            MouseArea {
++                id: mouseArea
++                anchors.fill: parent
++                onClicked: {
++                    if (root.direction == Qt.LeftToRight) {
++                        root.direction = Qt.RightToLeft;
++                    } else {
++                        root.direction = Qt.LeftToRight;
++                    }
++                }
++            }
++        }
++
++        Rectangle {
++            height: 50; width: parent.width
++            color: mouseArea2.pressed ? "black" : "gray"
++            Column {
++                anchors.centerIn: parent
++                Text {
++                    text: root.mirror ? "Mirrored" : "Not mirrored"
++                    color: "white"
++                    font.pixelSize: 16
++                    anchors.horizontalCenter: parent.horizontalCenter
++                }
++                Text {
++                    text: "(click here to toggle)"
++                    color: "white"
++                    font.pixelSize: 10
++                    font.italic: true
++                    anchors.horizontalCenter: parent.horizontalCenter
++                }
++            }
++            MouseArea {
++                id: mouseArea2
++                anchors.fill: parent
++                onClicked: {
++                    root.mirror = !root.mirror;
++                }
++            }
++        }
++    }
++
++    Component {
++        id: positionerDelegate
++        Rectangle {
++            width: 40; height: 40
++            color: Qt.rgba(0.8/(parent.value+1),0.8/(parent.value+1),0.8/(parent.value+1),1.0)
++            Text {
++                text: parent.parent.value+1
++                color: "white"
++                font.pixelSize: 18
++                anchors.centerIn: parent
++            }
++        }
++    }
++    Component {
++        id: viewDelegate
++        Item {
++            width: (listView.effectiveLayoutDirection == Qt.LeftToRight  ? (index == 48 - 1) : (index == 0)) ? 40 : 50
++            Rectangle {
++                width: 40; height: 40
++                color: Qt.rgba(0.5+(48 - index)*Math.random()/48,
++                               0.3+index*Math.random()/48,
++                               0.3*Math.random(),
++                               1.0)
++                Text {
++                    text: index+1
++                    color: "white"
++                    font.pixelSize: 18
++                    anchors.centerIn: parent
++                }
++            }
++        }
++    }
++}
++
index 0000000,0000000..33cbb3c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++import QmlProject 1.1
++
++Project {
++    mainFile: "layoutdirection.qml"
++
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..5c4739b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,313 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: root
++    property bool mirror: Qt.application.layoutDirection == Qt.RightToLeft
++    LayoutMirroring.enabled: mirror
++    LayoutMirroring.childrenInherit: true
++    width: 400
++    height: 875
++    color: "lightsteelblue"
++
++    Column {
++        spacing: 10
++        anchors { left: parent.left; right: parent.right; top: parent.top; margins: 10 }
++
++        Text {
++            text: "Positioners"
++            anchors.left: parent.left
++        }
++
++        Column {
++            id: positioners
++            spacing: 5
++            anchors.left: parent.left
++            Row {
++                id: row
++                spacing: 4
++                property string text: "THISISROW"
++                anchors.left: parent.left
++                Repeater {
++                    model: parent.text.length
++                    delegate: positionerDelegate
++                }
++            }
++            Flow {
++                id: flow
++                spacing: 4
++                width: 90
++                property string text: "THISISFLOW"
++                anchors.left: parent.left
++                Repeater {
++                    model: parent.text.length
++                    delegate: positionerDelegate
++                }
++            }
++            Grid {
++                id: grid
++                spacing: 4
++                columns: 6
++                property string text: "THISISGRID"
++                anchors.left: parent.left
++                Repeater {
++                    model: parent.text.length
++                    delegate: positionerDelegate
++                }
++            }
++            Component {
++                id: positionerDelegate
++                Text {
++                    color: "white"
++                    font.pixelSize: 20
++                    text: parent.text[index]
++                    Rectangle {
++                        z: -1
++                        opacity: 0.7
++                        color: "black"
++                        anchors.fill: parent
++                    }
++                }
++            }
++        }
++
++        Text {
++            text: "Text alignment"
++            anchors.left: parent.left
++        }
++
++        Rectangle {
++            id: textStrings
++            width: 148
++            height: 85
++            color: "white"
++            anchors.left: parent.left
++            Column {
++                spacing: 5
++                width: parent.width
++                anchors { fill: parent; margins: 5 }
++                Text {
++                    id: englishText
++                    width: parent.width
++                    text: "English text"
++                }
++                Text {
++                    id: arabicText
++                    width: parent.width
++                    text: "النص Ø§Ù„عربي"
++                }
++                Text {
++                    id: leftAlignedText
++                    width: parent.width
++                    text: "Text aligned to left"
++                    horizontalAlignment: Text.AlignLeft
++                }
++                Text {
++                    id: rightAlignedText
++                    width: parent.width
++                    text: "Text aligned to right"
++                    horizontalAlignment: Text.AlignRight
++                }
++            }
++        }
++
++        Text {
++            text: "Model views"
++            anchors.left: parent.left
++        }
++
++        Column {
++            id: views
++            spacing: 10
++            anchors.left: parent.left
++            ListView {
++                id: listView
++                z: -1
++                clip: true
++                model: text.length
++                width: 360; height: 45
++                orientation: Qt.Horizontal
++                property string text: "LISTVIEWLISTVIEWLISTVIEWLISTVIEWLISTVIEWLISTVIEW"
++                delegate: Rectangle {
++                    color: "black"
++                    width: 45; height: 45
++                    Rectangle {
++                        anchors { fill: parent; margins: 1 }
++                        color: "red"
++                    }
++                    Text {
++                        text: listView.text[index]
++                        font.pixelSize: 30
++                        anchors.centerIn: parent
++                    }
++                }
++            }
++            GridView {
++                id: gridView
++                z: -1
++                clip: true
++                model: text.length
++                width: 180; height: 90
++                cellWidth: 45; cellHeight: 45
++                property string text: "GRIDVIEWGRIDVIEWGRIDVIEWGRIDVIEWGRIDVIEWGRIDVIEW"
++                anchors.left: parent.left
++                delegate: Rectangle {
++                    color: "black"
++                    width: 45; height: 45
++                    Rectangle {
++                        anchors { fill: parent; margins: 1 }
++                        color: "red"
++                    }
++                    Text {
++                        anchors.centerIn: parent
++                        font.pixelSize: 30
++                        text: gridView.text[index]
++                    }
++                }
++            }
++        }
++
++        Text {
++            text: "Item x"
++            anchors.left: parent.left
++        }
++        Rectangle {
++            id: items
++            color: Qt.rgba(0.2, 0.2, 0.2, 0.6)
++            width: 275; height: 95
++            anchors.left: parent.left
++            Rectangle {
++                y: 5; x: 5
++                width: 130; height: 40
++                Text {
++                    text: "Item with x: 5\n(not mirrored)"
++                    anchors.centerIn: parent
++                }
++            }
++            Rectangle {
++                color:  Qt.rgba(0.7, 0.7, 0.7)
++                y: 50; x: mirror(5)
++                width: 130; height: 40
++                function mirror(value) {
++                    return LayoutMirroring.enabled ? (parent.width - width - value) : value;
++                }
++                Text {
++                    text: "Item with x: " + parent.x + "\n(manually mirrored)"
++                    anchors.centerIn: parent
++                }
++            }
++        }
++        Text {
++            text: "Item anchors"
++            anchors.left: parent.left
++        }
++
++        Rectangle {
++            id: anchoredItems
++            color: Qt.rgba(0.2, 0.2, 0.2, 0.6)
++            width: 270; height: 170
++            anchors.left: parent.left
++            Rectangle {
++                id: blackRectangle
++                color: "black"
++                width: 180; height: 90
++                anchors { horizontalCenter: parent.horizontalCenter; horizontalCenterOffset: 30 }
++                Text {
++                    text: "Horizontal center anchored\nwith offset 30\nto the horizontal center\nof the parent."
++                    color: "white"
++                    anchors.centerIn: parent
++                }
++            }
++            Rectangle {
++                id: whiteRectangle
++                color: "white"
++                width: 120; height: 70
++                anchors { left: parent.left; bottom: parent.bottom }
++                Text {
++                    text: "Left side anchored\nto the left side\nof the parent."
++                    color: "black"
++                    anchors.centerIn: parent
++                }
++            }
++            Rectangle {
++                id: grayRectangle
++                color: Qt.rgba(0.7, 0.7, 0.7)
++                width: 140; height: 90
++                anchors { right: parent.right; bottom: parent.bottom }
++                Text {
++                    text: "Right side anchored\nto the right side\nof the parent."
++                    anchors.centerIn: parent
++                }
++            }
++        }
++        Rectangle {
++            id: mirrorButton
++            color: mouseArea2.pressed ? "black" : "gray"
++            height: 50; width: parent.width
++            anchors.left: parent.left
++            Column {
++                anchors.centerIn: parent
++                Text {
++                    text: root.mirror ? "Mirrored" : "Not mirrored"
++                    color: "white"
++                    font.pixelSize: 16
++                    anchors.horizontalCenter: parent.horizontalCenter
++                }
++                Text {
++                    text: "(click here to toggle)"
++                    color: "white"
++                    font.pixelSize: 10
++                    font.italic: true
++                    anchors.horizontalCenter: parent.horizontalCenter
++                }
++            }
++            MouseArea {
++                id: mouseArea2
++                anchors.fill: parent
++                onClicked: {
++                    root.mirror = !root.mirror;
++                }
++            }
++        }
++    }
++}
++
index 0000000,0000000..72bc04a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++import QmlProject 1.1
++
++Project {
++    mainFile: "layoutmirroring.qml"
++
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..ef5b97b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,427 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: root
++    color: "white"
++    width: containerColumn.width
++    height: containerColumn.height + containerColumn.anchors.topMargin
++
++    property bool mirror: false
++    property variant horizontalAlignment: undefined
++
++    property variant editorType: ["Plain Text", "Styled Text", "Plain Rich Text", "Italic Rich Text", "Plain TextEdit", "Italic TextEdit", "TextInput"]
++    property variant text: ["", " ", "Hello world!", "مرحبا Ø§Ù„عالم!", "Hello world! Hello!\nHello world! Hello!", "مرحبا Ø§Ù„عالم! Ù…رحبا! Ù…رحبا Ø§Ù„عالم! Ù…رحبا!" ,"مرحبا Ø§Ù„عالم! Ù…رحبا! Ù…رحبا Hello world!\nالعالم! Ù…رحبا!"]
++    property variant description: ["empty text", "white-space-only text", "left-to-right text", "right-to-left text", "multi-line left-to-right text", "multi-line right-to-left text", "multi-line bidi text"]
++    property variant textComponents: [plainTextComponent, styledTextComponent, richTextComponent, italicRichTextComponent, plainTextEdit, italicTextEdit, textInput]
++
++    function shortText(horizontalAlignment) {
++
++        // all the different QML editors have
++        // the same alignment values
++        switch (horizontalAlignment) {
++        case Text.AlignLeft:
++            return "L";
++        case Text.AlignRight:
++            return "R";
++        case Text.AlignHCenter:
++            return "C";
++        case Text.AlignJustify:
++            return "J";
++        default:
++            return "Error";
++        }
++    }
++    Column {
++        id: containerColumn
++        spacing: 10
++        width: editorTypeRow.width
++        anchors { top: parent.top; topMargin: 5 }
++        Row {
++            id: editorTypeRow
++            Repeater {
++                model: editorType.length
++                Item {
++                    width: editorColumn.width
++                    height: editorColumn.height
++                    Column {
++                        id: editorColumn
++                        spacing: 5
++                        width: textColumn.width+10
++                        Text {
++                            text: root.editorType[index]
++                            font.pixelSize: 16
++                            anchors.horizontalCenter: parent.horizontalCenter
++                        }
++                        Column {
++                            id: textColumn
++                            spacing: 5
++                            anchors.horizontalCenter: parent.horizontalCenter
++                            Repeater {
++                                model: textComponents.length
++                                delegate: textComponents[index]
++                            }
++                        }
++                    }
++                }
++            }
++        }
++        Column {
++            spacing: 2
++            width: parent.width
++            Rectangle {
++                // button
++                height: 50; width: parent.width
++                color: mouseArea.pressed ? "black" : "lightgray"
++                Column {
++                    anchors.centerIn: parent
++                    Text {
++                        text: root.mirror ? "Mirrored" : "Not mirrored"
++                        color: "white"
++                        font.pixelSize: 16
++                        anchors.horizontalCenter: parent.horizontalCenter
++                    }
++                    Text {
++                        text: "(click here to toggle)"
++                        color: "white"
++                        font.pixelSize: 10
++                        font.italic: true
++                        anchors.horizontalCenter: parent.horizontalCenter
++                    }
++                }
++                MouseArea {
++                    id: mouseArea
++                    property int index: 0
++                    anchors.fill: parent
++                    onClicked: root.mirror = !root.mirror
++                }
++            }
++            Rectangle {
++                // button
++                height: 50; width: parent.width
++                color: mouseArea2.pressed ? "black" : "gray"
++                Column {
++                    anchors.centerIn: parent
++                    Text {
++                        text: {
++                            if (root.horizontalAlignment == undefined)
++                                return "Implict alignment";
++                            switch (root.horizontalAlignment) {
++                            case Text.AlignLeft:
++                                return "Left alignment";
++                            case Text.AlignRight:
++                                return "Right alignment";
++                            case Text.AlignHCenter:
++                                return "Center alignment";
++                            case Text.AlignJustify:
++                                return "Justify alignment";
++                            }
++                        }
++                        color: "white"
++                        font.pixelSize: 16
++                        anchors.horizontalCenter: parent.horizontalCenter
++                    }
++                    Text {
++                        text: "(click here to toggle)"
++                        color: "white"
++                        font.pixelSize: 10
++                        font.italic: true
++                        anchors.horizontalCenter: parent.horizontalCenter
++                    }
++                }
++                MouseArea {
++                    id: mouseArea2
++                    property int index: 0
++                    anchors.fill: parent
++                    onClicked: {
++                        if (index < 0) {
++                            root.horizontalAlignment = undefined;
++                        } else {
++                            root.horizontalAlignment = Math.pow(2, index);
++                        }
++                        index = (index + 2) % 5 - 1;
++                    }
++                }
++            }
++        }
++    }
++
++    Component {
++        id: plainTextComponent
++        Text {
++            width: 180
++            text: root.text[index]
++            font.pixelSize: 24
++            wrapMode: Text.WordWrap
++            horizontalAlignment: root.horizontalAlignment
++            LayoutMirroring.enabled: root.mirror
++            textFormat: Text.RichText
++            Rectangle {
++                z: -1
++                color: Qt.rgba(0.8, 0.2, 0.2, 0.3)
++                anchors.fill: parent
++            }
++            Text {
++                text: root.description[index]
++                color: Qt.rgba(1,1,1,1.0)
++                anchors.centerIn: parent
++                Rectangle {
++                    z: -1
++                    color: Qt.rgba(0.3, 0, 0, 0.3)
++                    anchors { fill: parent; margins: -3 }
++                }
++            }
++            Text {
++                color: "white"
++                text: shortText(parent.horizontalAlignment)
++                anchors { top: parent.top; right: parent.right; margins: 2 }
++            }
++        }
++    }
++
++    Component {
++        id: styledTextComponent
++        Text {
++            width: 180
++            text: root.text[index]
++            font.pixelSize: 24
++            wrapMode: Text.WordWrap
++            horizontalAlignment: root.horizontalAlignment
++            LayoutMirroring.enabled: root.mirror
++            textFormat: Text.RichText
++            style: Text.Sunken
++            styleColor: "white"
++            Rectangle {
++                z: -1
++                color: Qt.rgba(0.8, 0.2, 0.2, 0.3)
++                anchors.fill: parent
++            }
++            Text {
++                text: root.description[index]
++                color: Qt.rgba(1,1,1,1.0)
++                anchors.centerIn: parent
++                Rectangle {
++                    z: -1
++                    color: Qt.rgba(0.3, 0, 0, 0.3)
++                    anchors { fill: parent; margins: -3 }
++                }
++            }
++            Text {
++                color: "white"
++                text: shortText(parent.horizontalAlignment)
++                anchors { top: parent.top; right: parent.right; margins: 2 }
++            }
++        }
++    }
++
++    Component {
++        id: richTextComponent
++        Text {
++            width: 180
++            text: root.text[index]
++            font.pixelSize: 24
++            wrapMode: Text.WordWrap
++            horizontalAlignment: root.horizontalAlignment
++            LayoutMirroring.enabled: root.mirror
++            textFormat: Text.RichText
++            Rectangle {
++                z: -1
++                color: Qt.rgba(0.8, 0.2, 0.2, 0.3)
++                anchors.fill: parent
++            }
++            Text {
++                text: root.description[index]
++                color: Qt.rgba(1,1,1,1.0)
++                anchors.centerIn: parent
++                Rectangle {
++                    z: -1
++                    color: Qt.rgba(0.3, 0, 0, 0.3)
++                    anchors { fill: parent; margins: -3 }
++                }
++            }
++            Text {
++                color: "white"
++                text: shortText(parent.horizontalAlignment)
++                anchors { top: parent.top; right: parent.right; margins: 2 }
++            }
++        }
++    }
++
++    Component {
++        id: italicRichTextComponent
++        Text {
++            width: 180
++            text: "<i>" + root.text[index] + "</i>"
++            font.pixelSize: 24
++            wrapMode: Text.WordWrap
++            horizontalAlignment: root.horizontalAlignment
++            LayoutMirroring.enabled: root.mirror
++            textFormat: Text.RichText
++            property variant backgroundColor: Qt.rgba(0.8, 0.2, 0.2, 0.3)
++            Rectangle {
++                z: -1
++                color: parent.backgroundColor
++                anchors.fill: parent
++            }
++            Text {
++                text: root.description[index]
++                color: Qt.rgba(1,1,1,1.0)
++                anchors.centerIn: parent
++                Rectangle {
++                    z: -1
++                    color: Qt.rgba(0.3, 0, 0, 0.3)
++                    anchors { fill: parent; margins: -3 }
++                }
++            }
++            Text {
++                color: "white"
++                text: shortText(parent.horizontalAlignment)
++                anchors { top: parent.top; right: parent.right; margins: 2 }
++            }
++        }
++    }
++
++    Component {
++        id: plainTextEdit
++        TextEdit {
++            width: 180
++            text: root.text[index]
++            font.pixelSize: 24
++            cursorVisible: true
++            wrapMode: TextEdit.WordWrap
++            horizontalAlignment: root.horizontalAlignment
++            LayoutMirroring.enabled: root.mirror
++            Rectangle {
++                z: -1
++                color: Qt.rgba(0.5, 0.5, 0.2, 0.3)
++                anchors.fill: parent
++            }
++            Text {
++                text: root.description[index]
++                color: Qt.rgba(1,1,1,1.0)
++                anchors.centerIn: parent
++                Rectangle {
++                    z: -1
++                    color: Qt.rgba(0.3, 0, 0, 0.3)
++                    anchors { fill: parent; margins: -3 }
++                }
++            }
++            Text {
++                color: "white"
++                text: shortText(parent.horizontalAlignment)
++                anchors { top: parent.top; right: parent.right; margins: 2 }
++            }
++        }
++    }
++
++    Component {
++        id: italicTextEdit
++        TextEdit {
++            width: 180
++            text: "<i>" + root.text[index] + "<i>"
++            font.pixelSize: 24
++            cursorVisible: true
++            wrapMode: TextEdit.WordWrap
++            textFormat: TextEdit.RichText
++            horizontalAlignment: root.horizontalAlignment
++            LayoutMirroring.enabled: root.mirror
++            Rectangle {
++                z: -1
++                color: Qt.rgba(0.5, 0.5, 0.2, 0.3)
++                anchors.fill: parent
++            }
++            Text {
++                text: root.description[index]
++                color: Qt.rgba(1,1,1,1.0)
++                anchors.centerIn: parent
++                Rectangle {
++                    z: -1
++                    color: Qt.rgba(0.3, 0, 0, 0.3)
++                    anchors { fill: parent; margins: -3 }
++                }
++            }
++            Text {
++                color: "white"
++                text: shortText(parent.horizontalAlignment)
++                anchors { top: parent.top; right: parent.right; margins: 2 }
++            }
++        }
++    }
++
++    Component {
++        id: textInput
++        Item {
++            width: 180
++            height: textInput.text.length > 20 ? 3*textInput.height : textInput.height
++            TextInput {
++                id: textInput
++                width: 180
++                text: root.text[index]
++                font.pixelSize: 24
++                cursorVisible: true
++                horizontalAlignment: root.horizontalAlignment
++                LayoutMirroring.enabled: root.mirror
++                Rectangle {
++                    z: -1
++                    color: Qt.rgba(0.6, 0.4, 0.2, 0.3)
++                    anchors.fill: parent
++                }
++                Text {
++                    text: root.description[index]
++                    color: Qt.rgba(1,1,1,1.0)
++                    anchors.centerIn: parent
++                    Rectangle {
++                        z: -1
++                        color: Qt.rgba(0.3, 0, 0, 0.3)
++                        anchors { fill: parent; margins: -3 }
++                    }
++                }
++                Text {
++                    color: "white"
++                    text: shortText(parent.horizontalAlignment)
++                    anchors { top: parent.top; right: parent.right; margins: 2 }
++                }
++            }
++        }
++    }
++}
++
index 0000000,0000000..e4b5061
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++import QmlProject 1.1
++
++Project {
++    mainFile: "textalignment.qml"
++
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..ff5f628
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,93 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the QtQuick module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Item {
++    property real value: bar.x / (foo.width - bar.width)
++    Item {
++        id: foo
++        width: parent.width - 4
++        height: 6
++        anchors.centerIn: parent
++
++        Rectangle {
++            height: parent.height
++            anchors.left: parent.left
++            anchors.right: bar.horizontalCenter
++            color: "blue"
++            radius: 3
++        }
++        Rectangle {
++            height: parent.height
++            anchors.left: bar.horizontalCenter
++            anchors.right: parent.right
++            color: "gray"
++            radius: 3
++        }
++        Rectangle {
++            anchors.fill: parent
++            color: "transparent"
++            radius: 3
++            border.width: 2
++            border.color: "black"
++        }
++
++        Rectangle {
++            id: bar
++            y: -7
++            width: 20
++            height: 20
++            radius: 15
++            color: "white"
++            border.width: 2
++            border.color: "black"
++            MouseArea {
++                anchors.fill: parent
++                drag.target: parent
++                drag.axis: Drag.XAxis
++                drag.minimumX: 0
++                drag.maximumX: foo.width - parent.width
++            }
++        }
++    }
++}
++
index 0000000,0000000..3d66d72
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..7d3e97e
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..b820c81
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,315 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the QtQuick module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "content"
++
++Image {
++    width: 320
++    height: 480
++/*!
++    \title QML Examples - Shader Effects
++    \example declarative/shadereffects
++    \image qml-shadereffects-example.png
++    \brief This is a shader effects example
++
++    This example demonstrates a couple of visual effects that you can perform
++    with shaders in QtQuick 2.0
++*/
++    source: "../snake/content/pics/background.png"
++
++    Flickable {
++        anchors.fill: parent
++        contentWidth: 640
++        contentHeight: 360
++
++        ShaderEffectSource {
++            id: theSource
++            sourceItem: theItem
++            smooth: true
++        }
++
++        function saturate(x) {
++            return Math.min(Math.max(x, 0), 1)
++        }
++
++        function sliderToColor(x) {
++            return Qt.rgba(saturate(Math.max(2 - 6 * x, 6 * x - 4)),
++                            saturate(Math.min(6 * x, 4 - 6 * x)),
++                            saturate(Math.min(6 * x - 2, 6 - 6 * x)))
++        }
++
++        Grid {
++            anchors.centerIn: parent
++            columns: 3
++
++            Item {
++                id: theItem
++                width: 180
++                height: 180
++                ListView {
++                    anchors.centerIn: parent
++                    width: 160
++                    height: 140
++                    clip: true
++                    snapMode: ListView.SnapOneItem
++                    model: VisualItemModel {
++                        Text {
++                            width: 160
++                            height: 140
++                            horizontalAlignment: Text.AlignHCenter
++                            verticalAlignment: Text.AlignVCenter
++                            font.pixelSize: 120
++                            font.family: "Times"
++                            color: "blue"
++                            text: "Qt"
++                        }
++                        Image {
++                            width: 160
++                            height: 140
++                            source: "content/qt-logo.png"
++                            smooth: true
++                        }
++                        Image {
++                            width: 160
++                            height: 140
++                            source: "content/face-smile.png"
++                            smooth: true
++                        }
++                    }
++                }
++            }
++            ShaderEffect {
++                width: 180
++                height: 180
++                property variant source: theSource
++                property real amplitude: 0.04 * wobbleSlider.value
++                property real frequency: 20
++                property real time: 0
++                NumberAnimation on time { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 600 }
++                fragmentShader:
++                    "uniform lowp float qt_Opacity;" +
++                    "uniform highp float amplitude;" +
++                    "uniform highp float frequency;" +
++                    "uniform highp float time;" +
++                    "uniform sampler2D source;" +
++                    "varying highp vec2 qt_TexCoord0;" +
++                    "void main() {" +
++                    "    highp vec2 p = sin(time + frequency * qt_TexCoord0);" +
++                    "    gl_FragColor = texture2D(source, qt_TexCoord0 + amplitude * vec2(p.y, -p.x)) * qt_Opacity;" +
++                    "}"
++                Slider {
++                    id: wobbleSlider
++                    anchors.left: parent.left
++                    anchors.right: parent.right
++                    anchors.bottom: parent.bottom
++                    height: 40
++                }
++            }
++            ShaderEffect {
++                width: 180
++                height: 180
++                property variant source: theSource
++                property variant shadow: ShaderEffectSource {
++                    smooth: true
++                    sourceItem: ShaderEffect {
++                        width: theItem.width
++                        height: theItem.height
++                        property variant delta: Qt.size(0.0, 1.0 / height)
++                        property variant source: ShaderEffectSource {
++                            smooth: true
++                            sourceItem: ShaderEffect {
++                                width: theItem.width
++                                height: theItem.height
++                                property variant delta: Qt.size(1.0 / width, 0.0)
++                                property variant source: theSource
++                                fragmentShader: "
++                                    uniform lowp float qt_Opacity;
++                                    uniform sampler2D source;
++                                    uniform highp vec2 delta;
++                                    varying highp vec2 qt_TexCoord0;
++                                    void main() {
++                                        gl_FragColor =(0.0538 * texture2D(source, qt_TexCoord0 - 3.182 * delta)
++                                                     + 0.3229 * texture2D(source, qt_TexCoord0 - 1.364 * delta)
++                                                     + 0.2466 * texture2D(source, qt_TexCoord0)
++                                                     + 0.3229 * texture2D(source, qt_TexCoord0 + 1.364 * delta)
++                                                     + 0.0538 * texture2D(source, qt_TexCoord0 + 3.182 * delta)) * qt_Opacity;
++                                    }"
++                            }
++                        }
++                        fragmentShader: "
++                            uniform lowp float qt_Opacity;
++                            uniform sampler2D source;
++                            uniform highp vec2 delta;
++                            varying highp vec2 qt_TexCoord0;
++                            void main() {
++                                gl_FragColor =(0.0538 * texture2D(source, qt_TexCoord0 - 3.182 * delta)
++                                             + 0.3229 * texture2D(source, qt_TexCoord0 - 1.364 * delta)
++                                             + 0.2466 * texture2D(source, qt_TexCoord0)
++                                             + 0.3229 * texture2D(source, qt_TexCoord0 + 1.364 * delta)
++                                             + 0.0538 * texture2D(source, qt_TexCoord0 + 3.182 * delta)) * qt_Opacity;
++                            }"
++                    }
++                }
++                property real angle: 0
++                property variant offset: Qt.point(15.0 * Math.cos(angle), 15.0 * Math.sin(angle))
++                NumberAnimation on angle { loops: Animation.Infinite; from: 0; to: Math.PI * 2; duration: 6000 }
++                property variant delta: Qt.size(offset.x / width, offset.y / height)
++                property real darkness: shadowSlider.value
++                fragmentShader: "
++                    uniform lowp float qt_Opacity;
++                    uniform highp vec2 offset;
++                    uniform sampler2D source;
++                    uniform sampler2D shadow;
++                    uniform highp float darkness;
++                    uniform highp vec2 delta;
++                    varying highp vec2 qt_TexCoord0;
++                    void main() {
++                        lowp vec4 fg = texture2D(source, qt_TexCoord0);
++                        lowp vec4 bg = texture2D(shadow, qt_TexCoord0 + delta);
++                        gl_FragColor = (fg + vec4(0., 0., 0., darkness * bg.a) * (1. - fg.a)) * qt_Opacity;
++                    }"
++                Slider {
++                    id: shadowSlider
++                    anchors.left: parent.left
++                    anchors.right: parent.right
++                    anchors.bottom: parent.bottom
++                    height: 40
++                }
++            }
++            ShaderEffect {
++                width: 180
++                height: 180
++                property variant source: theSource
++                property variant delta: Qt.size(0.5 / width, 0.5 / height)
++                fragmentShader: "
++                    uniform sampler2D source;
++                    uniform highp vec2 delta;
++                    uniform highp float qt_Opacity;
++                    varying highp vec2 qt_TexCoord0;
++                    void main() {
++                        lowp vec4 tl = texture2D(source, qt_TexCoord0 - delta);
++                        lowp vec4 tr = texture2D(source, qt_TexCoord0 + vec2(delta.x, -delta.y));
++                        lowp vec4 bl = texture2D(source, qt_TexCoord0 - vec2(delta.x, -delta.y));
++                        lowp vec4 br = texture2D(source, qt_TexCoord0 + delta);
++                        lowp vec4 gx = (tl + bl) - (tr + br);
++                        lowp vec4 gy = (tl + tr) - (bl + br);
++                        gl_FragColor.xyz = vec3(0.);
++                        gl_FragColor.w = clamp(dot(sqrt(gx * gx + gy * gy), vec4(1.)), 0., 1.) * qt_Opacity;
++                    }"
++            }
++            ShaderEffect {
++                width: 180
++                height: 180
++                property variant source: theSource
++                property color tint: sliderToColor(colorizeSlider.value)
++                fragmentShader: "
++                    uniform sampler2D source;
++                    uniform lowp vec4 tint;
++                    uniform lowp float qt_Opacity;
++                    varying highp vec2 qt_TexCoord0;
++                    void main() {
++                        lowp vec4 c = texture2D(source, qt_TexCoord0);
++                        lowp float lo = min(min(c.x, c.y), c.z);
++                        lowp float hi = max(max(c.x, c.y), c.z);
++                        gl_FragColor = qt_Opacity * vec4(mix(vec3(lo), vec3(hi), tint.xyz), c.w);
++                    }"
++                Slider {
++                    id: colorizeSlider
++                    anchors.left: parent.left
++                    anchors.right: parent.right
++                    anchors.bottom: parent.bottom
++                    height: 40
++                }
++            }
++            ShaderEffect {
++                width: 180
++                height: 180
++                mesh: Qt.size(10, 10)
++                property variant source: theSource
++                property real bend: 0
++                property real minimize: 0
++                property real side: genieSlider.value
++                SequentialAnimation on bend {
++                    loops: Animation.Infinite
++                    NumberAnimation { to: 1; duration: 700; easing.type: Easing.InOutSine }
++                    PauseAnimation { duration: 1600 }
++                    NumberAnimation { to: 0; duration: 700; easing.type: Easing.InOutSine }
++                    PauseAnimation { duration: 1000 }
++                }
++                SequentialAnimation on minimize {
++                    loops: Animation.Infinite
++                    PauseAnimation { duration: 300 }
++                    NumberAnimation { to: 1; duration: 700; easing.type: Easing.InOutSine }
++                    PauseAnimation { duration: 1000 }
++                    NumberAnimation { to: 0; duration: 700; easing.type: Easing.InOutSine }
++                    PauseAnimation { duration: 1300 }
++                }
++                vertexShader: "
++                    uniform highp mat4 qt_Matrix;
++                    uniform highp float bend;
++                    uniform highp float minimize;
++                    uniform highp float side;
++                    uniform highp float width;
++                    uniform highp float height;
++                    attribute highp vec4 qt_Vertex;
++                    attribute highp vec2 qt_MultiTexCoord0;
++                    varying highp vec2 qt_TexCoord0;
++                    void main() {
++                        qt_TexCoord0 = qt_MultiTexCoord0;
++                        highp vec4 pos = qt_Vertex;
++                        pos.y = mix(qt_Vertex.y, height, minimize);
++                        highp float t = pos.y / height;
++                        t = (3. - 2. * t) * t * t;
++                        pos.x = mix(qt_Vertex.x, side * width, t * bend);
++                        gl_Position = qt_Matrix * pos;
++                    }"
++                Slider {
++                    id: genieSlider
++                    anchors.left: parent.left
++                    anchors.right: parent.right
++                    anchors.bottom: parent.bottom
++                    height: 40
++                }
++            }
++        }
++    }
++}
index 0000000,0000000..0b87259
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,57 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    width: 480; height: 640; color: "steelblue"
++
++    ListView {
++        anchors.fill: parent; model: Qt.fontFamilies()
++
++        delegate: Item {
++            height: 40; width: ListView.view.width
++            Text {
++                anchors.centerIn: parent
++                text: modelData; font.family: modelData; font.pixelSize: 24; color: "white"
++            }
++        }
++    }
++}
index 0000000,0000000..6c9aa25
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,61 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: screen
++
++    property int pixelSize: screen.height * 1.25
++    property color textColor: "lightsteelblue"
++    property string text: "Hello world! "
++
++    width: 640; height: 320
++    color: "steelblue"
++
++    Row {
++        y: -screen.height / 4.5
++
++        NumberAnimation on x { from: 0; to: -text.width; duration: 6000; loops: Animation.Infinite }
++        Text { id: text; font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text }
++        Text { font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text }
++        Text { font.pixelSize: screen.pixelSize; color: screen.textColor; text: screen.text }
++    }
++}
index 0000000,cf93f96..cf93f96
mode 000000,100644..100644
Binary files differ
index 0000000,0000000..78cef25
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,104 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    property string myText: "The quick brown fox jumps over the lazy dog."
++
++    width: 800; height: 480
++    color: "steelblue"
++
++    FontLoader { id: fixedFont; name: "Courier" }
++    FontLoader { id: localFont; source: "content/fonts/tarzeau_ocr_a.ttf" }
++    FontLoader { id: webFont; source: "http://www.princexml.com/fonts/steffmann/Starburst.ttf" }
++
++    Column {
++        anchors { fill: parent; leftMargin: 10; rightMargin: 10 }
++        spacing: 15
++
++        Text {
++            text: myText
++            color: "lightsteelblue"
++            width: parent.width
++            elide: Text.ElideRight
++            font.family: "Times"; font.pointSize: 42
++        }
++        Text {
++            text: myText
++            color: "lightsteelblue"
++            width: parent.width
++            elide: Text.ElideLeft
++            font { family: "Times"; pointSize: 42; capitalization: Font.AllUppercase }
++        }
++        Text {
++            text: myText
++            color: "lightsteelblue"
++            width: parent.width
++            elide: Text.ElideMiddle
++            font { family: fixedFont.name; pointSize: 42; weight: Font.Bold; capitalization: Font.AllLowercase }
++        }
++        Text {
++            text: myText
++            color: "lightsteelblue"
++            width: parent.width
++            elide: Text.ElideRight
++            font { family: fixedFont.name; pointSize: 42; italic: true; capitalization: Font.SmallCaps }
++        }
++        Text {
++            text: myText
++            color: "lightsteelblue"
++            width: parent.width
++            elide: Text.ElideLeft
++            font { family: localFont.name; pointSize: 42; capitalization: Font.Capitalize }
++        }
++        Text {
++            text: {
++                if (webFont.status == FontLoader.Ready) myText
++                else if (webFont.status == FontLoader.Loading) "Loading..."
++                else if (webFont.status == FontLoader.Error) "Error loading font"
++            }
++            color: "lightsteelblue"
++            width: parent.width
++            elide: Text.ElideMiddle
++            font.family: webFont.name; font.pointSize: 42
++        }
++    }
++}
index 0000000,0000000..d9479fb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,79 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: screen
++
++    width: 800; height: 480
++    color: "black"
++
++    Item {
++        id: container
++        x: screen.width / 2; y: screen.height / 2
++
++        Text {
++            id: text
++            anchors.centerIn: parent
++            color: "white"
++            text: "Hello world!"
++            font.pixelSize: 60
++            smooth: true
++
++            SequentialAnimation on font.letterSpacing {
++                loops: Animation.Infinite;
++                NumberAnimation { from: 0; to: 150; easing.type: Easing.InQuad; duration: 3000 }
++                ScriptAction {
++                    script: {
++                        container.y = (screen.height / 4) + (Math.random() * screen.height / 2)
++                        container.x = (screen.width / 4) + (Math.random() * screen.width / 2)
++                    }
++                }
++            }
++
++            SequentialAnimation on opacity {
++                loops: Animation.Infinite;
++                NumberAnimation { from: 1; to: 0; duration: 2600 }
++                PauseAnimation { duration: 400 }
++            }
++        }
++    }
++}
index 0000000,0000000..bc09aa2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,55 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Text {
++    width: parent.width
++    font.pointSize: 14
++    wrapMode: Text.WordWrap
++    textFormat: Text.StyledText
++    horizontalAlignment: main.hAlign
++
++    Rectangle {
++        border.color: "#efefef"
++        color: "transparent"
++        anchors.fill: parent
++    }
++}
index 0000000,24188b7..24188b7
mode 000000,100644..100644
Binary files differ
index 0000000,0000000..d05e0bf
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..e5e1d13
new file mode 100644 (file)
Binary files differ
index 0000000,cedd3ea..cedd3ea
mode 000000,100644..100644
Binary files differ
index 0000000,0000000..996719a
new file mode 100644 (file)
Binary files differ
index 0000000,132c20f..132c20f
mode 000000,100644..100644
Binary files differ
index 0000000,0000000..9d181af
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,101 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: main
++    width: 320; height: 480
++    focus: true
++
++    property var hAlign: Text.AlignLeft
++
++    Flickable {
++        anchors.fill: parent
++        contentWidth: parent.width
++        contentHeight: col.height + 20
++
++        Column {
++            id: col
++            x: 10; y: 10
++            spacing: 20
++            width: parent.width - 20
++
++            TextWithImage {
++                text: "This is a <b>happy</b> face<img src=\"images/face-smile.png\">"
++            }
++            TextWithImage {
++                text: "This is a <b>very<img src=\"images/face-smile-big.png\" align=\"middle\"/>happy</b> face aligned in the middle."
++            }
++            TextWithImage {
++                elide: Text.ElideRight
++                maximumLineCount: 2
++                text: "This is a sad face aligned to the top. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc rutrum dui pretium ipsum malesuada venenatis. Nulla sed turpis risus. Integer sit amet odio quis mauris varius venenatis<img src=\"images/face-sad.png\" align=\"top\">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc rutrum dui pretium ipsum malesuada venenatis. Nulla sed turpis risus. Integer sit amet odio quis mauris varius venenatis."
++            }
++            TextWithImage {
++                text: "This is a tiny<img src=\"images/face-smile.png\" width=\"15\" height=\"15\">happy face."
++            }
++            TextWithImage {
++                text: "This is a starfish<img src=\"images/starfish_2.png\" width=\"50\" height=\"50\" align=\"top\">aligned to the top and another one<img src=\"images/heart200.png\" width=\"50\" height=\"50\">aligned to the bottom."
++            }
++            TextWithImage {
++                text: "Qt logos<img src=\"images/qtlogo.png\" width=\"55\" height=\"60\" align=\"middle\"><img src=\"images/qtlogo.png\" width=\"37\" height=\"40\" align=\"middle\"><img src=\"images/qtlogo.png\" width=\"18\" height=\"20\" align=\"middle\">aligned in the middle with different sizes."
++            }
++            TextWithImage {
++                text: "Some hearts<img src=\"images/heart200.png\" width=\"20\" height=\"20\" align=\"bottom\"><img src=\"images/heart200.png\" width=\"30\" height=\"30\" align=\"bottom\"> <img src=\"images/heart200.png\" width=\"40\" height=\"40\"><img src=\"images/heart200.png\" width=\"50\" height=\"50\" align=\"bottom\">with different sizes."
++            }
++            TextWithImage {
++                text: "Resized image<img width=\"80\" height=\"76\" align=\"middle\" src=\"http://files.app4mobile.com/wp-content/uploads/2011/08/nokia-n9-price-specification-features-us-europe-india.jpg\">from the internet."
++            }
++            TextWithImage {
++                text: "Image<img align=\"middle\" src=\"http://qt.gitorious.org/images/sites/qt/logo.png\">from the internet."
++            }
++            TextWithImage {
++                height: 120
++                verticalAlignment: Text.AlignVCenter
++                text: "This is a <b>happy</b> face<img src=\"images/face-smile.png\"> with an explicit height."
++            }
++        }
++    }
++
++    Keys.onUpPressed: main.hAlign = Text.AlignHCenter
++    Keys.onLeftPressed: main.hAlign = Text.AlignLeft
++    Keys.onRightPressed: main.hAlign = Text.AlignRight
++}
index 0000000,0000000..4571330
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,107 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    id: main
++    width: 320; height: 480
++    focus: true
++
++    property real offset: 0
++    property real margin: 10
++
++    Keys.onLeftPressed: myText.horizontalAlignment = Text.AlignLeft
++    Keys.onUpPressed: myText.horizontalAlignment = Text.AlignHCenter
++    Keys.onRightPressed: myText.horizontalAlignment = Text.AlignRight
++    Keys.onDownPressed: myText.horizontalAlignment = Text.AlignJustify
++
++    Text {
++        id: myText
++        anchors.fill: parent
++        anchors.margins: 10
++        wrapMode: Text.WordWrap
++        font.family: "Times New Roman"
++        font.pixelSize: 13
++        textFormat: Text.StyledText
++        horizontalAlignment: Text.AlignJustify
++
++        text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer at ante dui sed eu egestas est facilis <a href=\"www.nokia.com\">www.nokia.com</a>.<br/>Curabitur ante est, pulvinar quis adipiscing a, iaculis id ipsum. Phasellus id neque id velit facilisis cursus ac sit amet nibh. Donec enim arcu, pharetra non semper nec, iaculis eget elit. Nunc blandit condimentum odio vel egestas.<br><ul type=\"bullet\"><li>Coffee<ol type=\"a\"><li>Espresso<li><b>Cappuccino</b><li><i>Flat White</i><li>Latte</ol><li>Juice<ol type=\"1\"><li>Orange</li><li>Apple</li><li>Pineapple</li><li>Tomato</li></ol></li></ul><p><font color=\"#434343\"><i>Proin consectetur <b>sapien</b> in ipsum lacinia sit amet mattis orci interdum. Quisque vitae accumsan lectus. Ut nisi turpis, sollicitudin ut dignissim id, fermentum ac est. Maecenas nec libero leo. Sed ac leo eget ipsum ultricies viverra sit amet eu orci. Praesent et tortor risus, viverra accumsan sapien. Sed faucibus eleifend lectus, sed euismod urna porta eu. Aenean ultricies lectus ut orci dictum quis convallis nisi ultrices. Nunc elit mi, iaculis a porttitor rutrum, venenatis malesuada nisi. Suspendisse turpis quam, euismod non imperdiet et, rutrum nec ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit."
++
++        onLineLaidOut: {
++            line.width = width / 2  - (2 * margin)
++            if (line.number === 30) {
++                main.offset = line.y
++            }
++            if (line.number >= 30) {
++                line.x = width / 2 + margin
++                line.y -= main.offset
++            }
++            if ((line.y + line.height) > rect.y && line.y < (rect.y + rect.height)) {
++                if (line.number < 30)
++                    line.width = Math.min((rect.x - line.x), line.width)
++                else {
++                    line.x = Math.max((rect.x + rect.width), width / 2 + margin)
++                    line.width = Math.min((width - margin - line.x), line.width)
++                }
++            }
++        }
++
++        Item {
++            id: rect
++            x: 28; y: 20
++            width: 60; height: 60
++
++            Rectangle {
++                anchors { fill: parent; leftMargin: 2; rightMargin: 2 }
++                color: "lightsteelblue"; opacity: 0.3
++            }
++
++            MouseArea {
++                anchors.fill: parent
++                drag.target: rect
++                acceptedButtons: Qt.LeftButton | Qt.RightButton
++                onClicked: mouse.button == Qt.RightButton ? myText.font.pixelSize -= 1 : myText.font.pixelSize += 1
++                onPositionChanged: myText.doLayout()
++            }
++        }
++    }
++
++}
index 0000000,9bfd290..9bfd290
mode 000000,100644..100644
--- /dev/null
index 0000000,0000000..c08d9b9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++import QmlProject 1.1
++
++Project {
++    mainFile: "text.qml"
++
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..1a4bc5d
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..4f51f24
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++border.left: 0
++border.top: 6
++border.bottom: 6
++border.right: 6
++source: endHandle.png
index 0000000,0000000..deedcd5
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..f9eae20
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++border.left: 6
++border.top: 6
++border.bottom: 6
++border.right: 0
++source: startHandle.png
index 0000000,0000000..7938ce5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,211 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++import QtQuick 2.0
++
++Rectangle {
++    id: editor
++    color: "lightGrey"
++    width: 640; height: 480
++
++    Rectangle {
++        color: "white"
++        anchors.fill: parent
++        anchors.margins: 20
++
++        BorderImage {
++            id: startHandle
++            source: "pics/startHandle.sci"
++            opacity: 0.0
++            width: 10
++            x: edit.positionToRectangle(edit.selectionStart).x - flick.contentX-width
++            y: edit.positionToRectangle(edit.selectionStart).y - flick.contentY
++            height: edit.positionToRectangle(edit.selectionStart).height
++        }
++
++        BorderImage {
++            id: endHandle
++            source: "pics/endHandle.sci"
++            opacity: 0.0
++            width: 10
++            x: edit.positionToRectangle(edit.selectionEnd).x - flick.contentX
++            y: edit.positionToRectangle(edit.selectionEnd).y - flick.contentY
++            height: edit.positionToRectangle(edit.selectionEnd).height
++        }
++
++        Flickable {
++            id: flick
++
++            anchors.fill: parent
++            contentWidth: edit.paintedWidth
++            contentHeight: edit.paintedHeight
++            interactive: true
++            clip: true
++
++            function ensureVisible(r) {
++                if (contentX >= r.x)
++                    contentX = r.x;
++                else if (contentX+width <= r.x+r.width)
++                    contentX = r.x+r.width-width;
++                if (contentY >= r.y)
++                    contentY = r.y;
++                else if (contentY+height <= r.y+r.height)
++                    contentY = r.y+r.height-height;
++            }
++
++            TextEdit {
++                id: edit
++                width: flick.width
++                height: flick.height
++                focus: true
++                wrapMode: TextEdit.Wrap
++                textFormat: TextEdit.RichText
++
++                onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
++
++                text: "<h1>Text Selection</h1>"
++                    +"<p>This example is a whacky text selection mechanisms, showing how these can be implemented in the TextEdit element, to cater for whatever style is appropriate for the target platform."
++                    +"<p><b>Press-and-hold</b> to select a word, then drag the selection handles."
++                    +"<p><b>Drag outside the selection</b> to scroll the text."
++                    +"<p><b>Click inside the selection</b> to cut/copy/paste/cancel selection."
++                    +"<p>It's too whacky to let you paste if there is no current selection."
++
++            }
++        }
++
++        Item {
++            id: menu
++            opacity: 0.0
++            width: 100
++            height: 120
++            anchors.centerIn: parent
++
++            Rectangle {
++                border.width: 1
++                border.color: "darkBlue"
++                radius: 15
++                color: "#806080FF"
++                anchors.fill: parent
++            }
++
++            Column {
++                anchors.centerIn: parent
++                spacing: 8
++
++                Rectangle {
++                    border.width: 1
++                    border.color: "darkBlue"
++                    color: "#ff7090FF"
++                    width: 60
++                    height: 16
++
++                    Text { anchors.centerIn: parent; text: "Cut" }
++
++                    MouseArea { 
++                        anchors.fill: parent
++                        onClicked: { edit.cut(); editor.state = "" } 
++                    }
++                }
++
++                Rectangle {
++                    border.width: 1
++                    border.color: "darkBlue"
++                    color: "#ff7090FF"
++                    width: 60
++                    height: 16
++
++                    Text { anchors.centerIn: parent; text: "Copy" }
++
++                    MouseArea { 
++                        anchors.fill: parent
++                        onClicked: { edit.copy(); editor.state = "selection" } 
++                    }
++                }
++
++                Rectangle {
++                    border.width: 1
++                    border.color: "darkBlue"
++                    color: "#ff7090FF"
++                    width: 60
++                    height: 16
++
++                    Text { anchors.centerIn: parent; text: "Paste" }
++
++                    MouseArea { 
++                        anchors.fill: parent
++                        onClicked: { edit.paste(); edit.cursorPosition = edit.selectionEnd; editor.state = "" } 
++                    }
++                }
++
++                Rectangle {
++                    border.width: 1
++                    border.color: "darkBlue"
++                    color: "#ff7090FF"
++                    width: 60
++                    height: 16
++
++                    Text { anchors.centerIn: parent; text: "Deselect" }
++
++                    MouseArea { 
++                        anchors.fill: parent
++                        onClicked: { 
++                            edit.cursorPosition = edit.selectionEnd;
++                            edit.deselect();
++                            editor.state = "" 
++                        } 
++                    }
++                }
++            }
++        }
++    }
++
++    states: [
++        State {
++            name: "selection"
++            PropertyChanges { target: startHandle; opacity: 1.0 }
++            PropertyChanges { target: endHandle; opacity: 1.0 }
++        },
++        State {
++            name: "menu"
++            PropertyChanges { target: startHandle; opacity: 0.5 }
++            PropertyChanges { target: endHandle; opacity: 0.5 }
++            PropertyChanges { target: menu; opacity: 1.0 }
++        }
++    ]
++}
index 0000000,0000000..4d2aab3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,49 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++// ![0]
++WorkerScript.onMessage = function(msg) {
++    if (msg.action == 'appendCurrentTime') {
++        var data = {'time': new Date().toTimeString()};
++        msg.model.append(data);
++        msg.model.sync();   // updates the changes to the list
++    }
++}
++// ![0]
index 0000000,0000000..e7c8e69
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,56 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QmlProject 1.1
++
++Project {
++    mainFile: "timedisplay.qml"
++
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..48d0f65
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,76 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++// ![0]
++import QtQuick 2.0
++
++Rectangle {
++    color: "white"
++    width: 200
++    height: 300
++
++    ListView {
++        anchors.fill: parent
++        model: listModel
++        delegate: Component {
++            Text { text: time }
++        }
++
++        ListModel { id: listModel }
++
++        WorkerScript {
++            id: worker
++            source: "dataloader.js"
++        }
++
++        Timer {
++            id: timer
++            interval: 2000; repeat: true
++            running: true
++            triggeredOnStart: true
++
++            onTriggered: {
++                var msg = {'action': 'appendCurrentTime', 'model': listModel};
++                worker.sendMessage(msg);
++            }
++        }
++    }
++}
++// ![0]
index 0000000,0000000..f76471f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,15 @@@
++var lastx = 0;
++var lasty = 0;
++
++WorkerScript.onMessage = function(message) {
++    var ydiff = message.y - lasty;
++    var xdiff = message.x - lastx;
++
++    var total = Math.sqrt(ydiff * ydiff + xdiff * xdiff);
++
++    lastx = message.x;
++    lasty = message.y;
++
++    WorkerScript.sendMessage( {xmove: xdiff, ymove: ydiff, move: total} );
++}
++
index 0000000,0000000..7fced81
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,83 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    width: 480; height: 320
++
++    WorkerScript {
++        id: myWorker
++        source: "workerscript.js"
++
++        onMessage: {
++            console.log("Moved " + messageObject.xmove + " along the X axis.");
++            console.log("Moved " + messageObject.ymove + " along the Y axis.");
++            console.log("Moved " + messageObject.move + " pixels.");
++        }
++    }
++
++    Rectangle {
++        width: 200; height: 200
++        anchors.left: parent.left; anchors.leftMargin: 20
++        color: "red"
++
++        MouseArea { 
++            anchors.fill: parent
++            onClicked: myWorker.sendMessage( { rectangle: "red", x: mouse.x, y: mouse.y } );
++        }
++    }
++
++    Rectangle {
++        width: 200; height: 200
++        anchors.right: parent.right; anchors.rightMargin: 20
++        color: "blue"
++
++        MouseArea { 
++            anchors.fill: parent
++            onClicked: myWorker.sendMessage( { rectangle: "blue", x: mouse.x, y: mouse.y } );
++        }
++    }
++
++    Text {
++        text: "Click a Rectangle!"
++        anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: 50 }
++    }
++}
index 0000000,0000000..6d7a91f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++import QmlProject 1.1
++
++Project {
++    mainFile: "workerscript.qml"
++
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,0000000..7fe625c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,153 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Component {
++    Item {
++        property variant stickies
++
++        id: page
++        width: ListView.view.width+40; height: ListView.view.height
++
++
++        Image { 
++            source: "cork.jpg"
++            width: page.ListView.view.width
++            height: page.ListView.view.height
++            fillMode: Image.PreserveAspectCrop
++            clip: true
++        }
++
++        MouseArea {
++            anchors.fill: parent
++            onClicked: page.focus = false;
++        }
++
++        Text {
++            text: name; x: 15; y: 8; height: 40; width: 370
++            font.pixelSize: 18; font.bold: true; color: "white"
++            style: Text.Outline; styleColor: "black"
++        }
++
++        Repeater {
++            model: notes
++            Item {
++                id: stickyPage
++
++                property int randomX: Math.random() * (page.ListView.view.width-0.5*stickyImage.width) +100
++                property int randomY: Math.random() * (page.ListView.view.height-0.5*stickyImage.height) +50
++
++                x: randomX; y: randomY
++
++                rotation: -flickable.horizontalVelocity / 100;
++                Behavior on rotation {
++                    SpringAnimation { spring: 2.0; damping: 0.15 }
++                }
++
++                Item {
++                    id: sticky
++                    scale: 0.7
++
++                    Image {
++                        id: stickyImage
++                        x: 8 + -width * 0.6 / 2; y: -20
++                        source: "note-yellow.png"
++                        scale: 0.6; transformOrigin: Item.TopLeft
++                        smooth: true
++                    }
++
++                    TextEdit {
++                        id: myText
++                        x: -104; y: 36; width: 215; height: 200
++                        smooth: true
++                        font.pixelSize: 24
++                        readOnly: false
++                        rotation: -8
++                        text: noteText
++                    }
++
++                    Item {
++                        x: stickyImage.x; y: -20
++                        width: stickyImage.width * stickyImage.scale
++                        height: stickyImage.height * stickyImage.scale
++
++                        MouseArea {
++                            id: mouse
++                            anchors.fill: parent
++                            drag.target: stickyPage
++                            drag.axis: Drag.XandYAxis
++                            drag.minimumY: 0
++                            drag.maximumY: page.height - 80
++                            drag.minimumX: 100
++                            drag.maximumX: page.width - 140
++                            onClicked: { myText.focus = true; myText.openSoftwareInputPanel(); }
++                        }
++                    }
++                }
++
++                Image {
++                    x: -width / 2; y: -height * 0.5 / 2
++                    source: "tack.png"
++                    scale: 0.7; transformOrigin: Item.TopLeft
++                }
++
++                states: State {
++                    name: "pressed"
++                    when: mouse.pressed
++                    PropertyChanges { target: sticky; rotation: 8; scale: 1 }
++                    PropertyChanges { target: page; z: 8 }
++                }
++
++                transitions: Transition {
++                    NumberAnimation { properties: "rotation,scale"; duration: 200 }
++                }
++            }
++        }
++    }
++}
++
++
++
++
++
++
++
++
index 0000000,0000000..160bc00
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..8ddecc8
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..cef2d1c
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..dc3aa6b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,116 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import "content"
++
++Rectangle {
++    width: 800; height: 480
++    color: "#464646"
++
++    ListModel {
++        id: list
++
++        ListElement {
++            name: "Sunday"
++            notes: [ 
++                ListElement { noteText: "Lunch" },
++                ListElement { noteText: "Birthday Party" }
++            ]
++        }
++        
++        ListElement {
++            name: "Monday"
++            notes: [
++                ListElement { noteText: "Pickup kids from\nschool\n4.30pm" },
++                ListElement { noteText: "Checkout Qt" }, ListElement { noteText: "Read email" }
++            ]
++        }
++
++        ListElement {
++            name: "Tuesday"
++            notes: [
++                ListElement { noteText: "Walk dog" },
++                ListElement { noteText: "Buy newspaper" }
++            ]
++        }
++
++        ListElement {
++            name: "Wednesday"
++            notes: [ ListElement { noteText: "Cook dinner" } ]
++        }
++
++        ListElement {
++            name: "Thursday"
++            notes: [
++                ListElement { noteText: "Meeting\n5.30pm" },
++                ListElement { noteText: "Weed garden" }
++            ]
++        }
++
++        ListElement {
++            name: "Friday"
++            notes: [
++                ListElement { noteText: "More work" },
++                ListElement { noteText: "Grocery shopping" }
++            ]
++        }
++
++        ListElement {
++            name: "Saturday"
++            notes: [
++                ListElement { noteText: "Drink" },
++                ListElement { noteText: "Download Qt\nPlay with QML" }
++            ]
++        }
++    }
++
++    ListView {
++        id: flickable
++
++        anchors.fill: parent
++        focus: true
++        highlightRangeMode: ListView.StrictlyEnforceRange
++        orientation: ListView.Horizontal
++        snapMode: ListView.SnapOneItem
++        model: list
++        delegate: Day { }
++    }
++}
index 0000000,0000000..db46473
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,133 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++import QtQuick 2.0
++import QtQuick.Particles 2.0
++import "content"
++
++Item {
++    id: root
++    height: 640
++    width: 320
++    Item {
++        id: startScreen
++        anchors.fill: parent
++        z: 1000
++        Image {
++            source: "content/title.png"
++            anchors.centerIn: parent
++        }
++        MouseArea{
++            anchors.fill: parent
++            onClicked: {//Game Start
++                parent.visible = false;
++            }
++        }
++    }
++    Rectangle {
++        id: bg
++        anchors.fill: parent
++        gradient: Gradient {
++            GradientStop { position: 0.0; color: "DarkBlue" }
++            GradientStop { position: 0.8; color: "SkyBlue" }
++            GradientStop { position: 0.81; color: "ForestGreen" }
++            GradientStop { position: 1.0; color: "DarkGreen" }
++        }
++    }
++
++    BearWhackParticleSystem {
++        id: particleSystem
++        anchors.fill: parent
++        running: !startScreen.visible
++    }
++
++    property int score: 0
++
++    Text {
++        anchors.right: parent.right
++        anchors.margins: 4
++        anchors.top: parent.top
++        color: "white"
++        function padded(num) {
++            var ret = num.toString();
++            while (ret.length < 6)
++                ret = "0" + ret;
++            return ret;
++        }
++        text: "Score: " + padded(score)
++    }
++    MultiPointTouchArea {
++        anchors.fill: parent
++        touchPoints: [//Support up to 4 touches at once?
++            AugmentedTouchPoint{ system: particleSystem },
++            AugmentedTouchPoint{ system: particleSystem },
++            AugmentedTouchPoint{ system: particleSystem },
++            AugmentedTouchPoint{ system: particleSystem }
++        ]
++    }
++    MouseArea{
++        anchors.fill: parent
++        id: ma
++        onPressedChanged: {
++            if (pressed) {
++                timer.restart();
++                sgoal.enabled = true;
++                particleSystem.explode(mouseX,mouseY);
++            }
++        }
++        Timer {
++            id: timer
++            interval: 100
++            running: false
++            repeat: false
++            onTriggered: sgoal.enabled = false
++        }
++        SpriteGoal {
++            id: sgoal
++            x: ma.mouseX - 16
++            y: ma.mouseY - 16
++            width: 32
++            height: 32
++            system: particleSystem
++            parent: particleSystem
++            goalState: "falling"
++            enabled: false
++        }
++    }
++}
index 0000000,0000000..aede1a8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,70 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++import QtQuick 2.0
++import QtQuick.Particles 2.0
++
++TouchPoint {
++    id: container
++    property ParticleSystem system
++    onPressedChanged: {
++        if (pressed) {
++            timer.restart();
++            child.enabled = true;
++            system.explode(x,y);
++        }
++    }
++    property QtObject obj: Timer {
++        id: timer
++        interval: 100
++        running: false
++        repeat: false
++        onTriggered: child.enabled = false
++    }
++    property Item child: SpriteGoal {
++        enabled: false
++        x: container.area.x - 16
++        y: container.area.y - 16
++        width: container.area.width + 32
++        height: container.area.height + 32 //+32 so it doesn't have to hit the exact center
++        system: container.system
++        parent: container.system
++        goalState: "falling"
++    }
++}
index 0000000,0000000..64a02ce
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..3b88f3b
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..337b636
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..f0e6859
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..c9a84ae
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..9788c5c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,65 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++import QtQuick.Particles 2.0
++
++ParticleSystem {
++    property alias color: img.color
++    property alias emitting: emitter.enabled
++    ImageParticle {
++        id: img
++        source: "blur-circle.png"
++        colorVariation: 0.1
++        color: "#ff521d"
++        alpha: 0
++    }
++    Emitter {
++        id: emitter
++        speedFromMovement: 20
++        emitRate: 80
++        lifeSpan: 1500
++        speed: PointDirection{ y: -90; yVariation: 50; }
++        acceleration: PointDirection{ xVariation: 100; yVariation: 90; }
++        size: 51
++        sizeVariation: 53
++        endSize: 64
++    }
++}
index 0000000,0000000..1b03cd0
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..dbc39cb
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..dbc3880
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..d630ea2
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..72a0ce2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,91 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++import QtQuick 2.0
++import "content"
++
++Rectangle {
++    width: 360
++    height: 480
++    color: "black"
++
++    MultiPointTouchArea {
++        anchors.fill: parent
++        minimumTouchPoints: 1
++        maximumTouchPoints: 5
++        touchPoints: [
++            TouchPoint { id: touch1 },
++            TouchPoint { id: touch2 },
++            TouchPoint { id: touch11 },
++            TouchPoint { id: touch21 },
++            TouchPoint { id: touch31 }
++        ]
++    }
++
++    ParticleFlame {
++        color: "red"
++        x: touch1.x
++        y: touch1.y
++        emitting: touch1.pressed
++    }
++    ParticleFlame {
++        color: "green"
++        x: touch2.x
++        y: touch2.y
++        emitting: touch2.pressed
++    }
++    ParticleFlame {
++        color: "yellow"
++        x: touch11.x
++        y: touch11.y
++        emitting: touch11.pressed
++    }
++    ParticleFlame {
++        color: "blue"
++        x: touch21.x
++        y: touch21.y
++        emitting: touch21.pressed
++    }
++    ParticleFlame {
++        color: "violet"
++        x: touch31.x
++        y: touch31.y
++        emitting: touch31.pressed
++    }
++}
index 0000000,0000000..037766e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,97 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the examples of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:BSD$
++** You may use this file under the terms of the BSD license as follows:
++**
++** "Redistribution and use in source and binary forms, with or without
++** modification, are permitted provided that the following conditions are
++** met:
++**   * Redistributions of source code must retain the above copyright
++**     notice, this list of conditions and the following disclaimer.
++**   * Redistributions in binary form must reproduce the above copyright
++**     notice, this list of conditions and the following disclaimer in
++**     the documentation and/or other materials provided with the
++**     distribution.
++**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
++**     the names of its contributors may be used to endorse or promote
++**     products derived from this software without specific prior written
++**     permission.
++**
++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import QtQuick 2.0
++
++Rectangle {
++    width: 640
++    height: 360
++    color: "gray"
++
++    Flickable {
++        id: flick
++        anchors.fill: parent
++        contentWidth: 500
++        contentHeight: 500
++
++        PinchArea {
++            width: Math.max(flick.contentWidth, flick.width)
++            height: Math.max(flick.contentHeight, flick.height)
++
++            property real initialWidth
++            property real initialHeight
++            onPinchStarted: {
++                initialWidth = flick.contentWidth
++                initialHeight = flick.contentHeight
++            }
++
++            onPinchUpdated: {
++                // adjust content pos due to drag
++                flick.contentX += pinch.previousCenter.x - pinch.center.x
++                flick.contentY += pinch.previousCenter.y - pinch.center.y
++
++                // resize content
++                flick.resizeContent(initialWidth * pinch.scale, initialHeight * pinch.scale, pinch.center)
++            }
++
++            onPinchFinished: {
++                // Move its content within bounds.
++                flick.returnToBounds()
++            }
++
++            Rectangle {
++                width: flick.contentWidth
++                height: flick.contentHeight
++                color: "white"
++                Image {
++                    anchors.fill: parent
++                    source: "qt-logo.jpg"
++                    MouseArea {
++                        anchors.fill: parent
++                        onDoubleClicked: {
++                            flick.contentWidth = 500
++                            flick.contentHeight = 500
++                        }
++                    }
++                }
++            }
++        }
++    }
++}
index 0000000,0000000..4014b46
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..a9aa9d2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++import QmlProject 1.1
++
++Project {
++    mainFile: "touchinteraction.qml"
++
++    /* Include .qml, .js, and image files from current directory and subdirectories */
++    QmlFiles {
++        directory: "."
++    }
++    JavaScriptFiles {
++        directory: "."
++    }
++    ImageFiles {
++        directory: "."
++    }
++}
index 0000000,affc57c..8ed66f8
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,5 +1,5 @@@
 -QT += declarative quick
++QT += qml quick
+ HEADERS += piechart.h
+ SOURCES += piechart.cpp \
+            main.cpp
index 0000000,affc57c..8ed66f8
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,5 +1,5 @@@
 -QT += declarative quick
++QT += qml quick
+ HEADERS += piechart.h
+ SOURCES += piechart.cpp \
+            main.cpp
index 0000000,affc57c..8ed66f8
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,5 +1,5 @@@
 -QT += declarative quick
++QT += qml quick
+ HEADERS += piechart.h
+ SOURCES += piechart.cpp \
+            main.cpp
index 0000000,6724fa0..23eb222
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,7 +1,7 @@@
 -QT += declarative quick
++QT += qml quick
+ HEADERS += piechart.h \
+            pieslice.h 
+ SOURCES += piechart.cpp \
+            pieslice.cpp \
+            main.cpp
index 0000000,6724fa0..23eb222
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,7 +1,7 @@@
 -QT += declarative quick
++QT += qml quick
+ HEADERS += piechart.h \
+            pieslice.h 
+ SOURCES += piechart.cpp \
+            pieslice.cpp \
+            main.cpp
index 0000000,bfcb607..9109165
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,72 +1,72 @@@
 -QDeclarativeListProperty<PieSlice> PieChart::slices() 
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the documentation of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #include "piechart.h"
+ #include "pieslice.h"
+ PieChart::PieChart(QQuickItem *parent)
+     : QQuickItem(parent)
+ {
+ }
+ QString PieChart::name() const
+ {
+     return m_name;
+ }
+ void PieChart::setName(const QString &name)
+ {
+     m_name = name;
+ }
+ //![0]
 -    return QDeclarativeListProperty<PieSlice>(this, 0, &PieChart::append_slice);
++QQmlListProperty<PieSlice> PieChart::slices()
+ {
 -void PieChart::append_slice(QDeclarativeListProperty<PieSlice> *list, PieSlice *slice)
++    return QQmlListProperty<PieSlice>(this, 0, &PieChart::append_slice);
+ }
++void PieChart::append_slice(QQmlListProperty<PieSlice> *list, PieSlice *slice)
+ {
+     PieChart *chart = qobject_cast<PieChart *>(list->object);
+     if (chart) {
+         slice->setParentItem(chart);
+         chart->m_slices.append(slice);
+     }
+ }
+ //![0]
index 0000000,9beabda..6c17bc1
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,75 +1,75 @@@
 -    Q_PROPERTY(QDeclarativeListProperty<PieSlice> slices READ slices)
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the documentation of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #ifndef PIECHART_H
+ #define PIECHART_H
+ #include <QtQuick/QQuickItem>
+ class PieSlice;
+ //![0]
+ class PieChart : public QQuickItem
+ {
+     Q_OBJECT
 -    QDeclarativeListProperty<PieSlice> slices();
++    Q_PROPERTY(QQmlListProperty<PieSlice> slices READ slices)
+ //![0]
+     Q_PROPERTY(QString name READ name WRITE setName)
+ //![1]
+ public:
+ //![1]
+     PieChart(QQuickItem *parent = 0);
+     QString name() const;
+     void setName(const QString &name);
+ //![2]
 -    static void append_slice(QDeclarativeListProperty<PieSlice> *list, PieSlice *slice);
++    QQmlListProperty<PieSlice> slices();
+ private:
++    static void append_slice(QQmlListProperty<PieSlice> *list, PieSlice *slice);
+     QString m_name;
+     QList<PieSlice *> m_slices;
+ };
+ //![2]
+ #endif
index 0000000,c243ec4..75f88b2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,18 +1,18 @@@
 -QT += declarative quick
+ TEMPLATE = lib
+ CONFIG += qt plugin
++QT += qml quick
+ DESTDIR = ChartsPlugin
+ TARGET = chartsplugin
+ OBJECTS_DIR = tmp
+ MOC_DIR = tmp
+ HEADERS += piechart.h \
+            pieslice.h \
+            chartsplugin.h
+ SOURCES += piechart.cpp \
+            pieslice.cpp \
+            chartsplugin.cpp
index 0000000,d75f810..0cead52
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,53 +1,53 @@@
 -#include <qdeclarative.h>
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the documentation of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #include "chartsplugin.h"
+ //![0]
+ #include "piechart.h"
+ #include "pieslice.h"
++#include <qqml.h>
+ void ChartsPlugin::registerTypes(const char *uri)
+ {
+     qmlRegisterType<PieChart>(uri, 1, 0, "PieChart");
+     qmlRegisterType<PieSlice>(uri, 1, 0, "PieSlice");
+ }
+ //![0]
index 0000000,863564b..4db1b01
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,57 +1,57 @@@
 -#include <QDeclarativeExtensionPlugin>
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the documentation of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #ifndef CHARTSPLUGIN_H
+ #define CHARTSPLUGIN_H
+ //![0]
 -class ChartsPlugin : public QDeclarativeExtensionPlugin
++#include <QQmlExtensionPlugin>
 -    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "chartsplugin.json")
++class ChartsPlugin : public QQmlExtensionPlugin
+ {
+     Q_OBJECT
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "chartsplugin.json")
+ public:
+     void registerTypes(const char *uri);
+ };
+ //![0]
+ #endif
index 0000000,2a8f402..b188e39
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,71 +1,71 @@@
 -QDeclarativeListProperty<PieSlice> PieChart::slices() 
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the documentation of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #include "piechart.h"
+ #include "pieslice.h"
+ PieChart::PieChart(QQuickItem *parent)
+     : QQuickItem(parent)
+ {
+ }
+ QString PieChart::name() const
+ {
+     return m_name;
+ }
+ void PieChart::setName(const QString &name)
+ {
+     m_name = name;
+ }
 -    return QDeclarativeListProperty<PieSlice>(this, 0, &PieChart::append_slice);
++QQmlListProperty<PieSlice> PieChart::slices()
+ {
 -void PieChart::append_slice(QDeclarativeListProperty<PieSlice> *list, PieSlice *slice)
++    return QQmlListProperty<PieSlice>(this, 0, &PieChart::append_slice);
+ }
++void PieChart::append_slice(QQmlListProperty<PieSlice> *list, PieSlice *slice)
+ {
+     PieChart *chart = qobject_cast<PieChart *>(list->object);
+     if (chart) {
+         slice->setParentItem(chart);
+         chart->m_slices.append(slice);
+     }
+ }
index 0000000,fe6b96a..2ee8108
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,69 +1,69 @@@
 -    Q_PROPERTY(QDeclarativeListProperty<PieSlice> slices READ slices)
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the documentation of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #ifndef PIECHART_H
+ #define PIECHART_H
+ #include <QtQuick/QQuickItem>
+ class PieSlice;
+ class PieChart : public QQuickItem
+ {
+     Q_OBJECT
 -    QDeclarativeListProperty<PieSlice> slices();
++    Q_PROPERTY(QQmlListProperty<PieSlice> slices READ slices)
+     Q_PROPERTY(QString name READ name WRITE setName)
+ public:
+     PieChart(QQuickItem *parent = 0);
+     QString name() const;
+     void setName(const QString &name);
 -    static void append_slice(QDeclarativeListProperty<PieSlice> *list, PieSlice *slice);
++    QQmlListProperty<PieSlice> slices();
+ private:
++    static void append_slice(QQmlListProperty<PieSlice> *list, PieSlice *slice);
+     QString m_name;
+     QList<PieSlice *> m_slices;
+ };
+ #endif
  #ifndef DIALOGPLUGIN_H
  #define DIALOGPLUGIN_H
  
 -#include <QtDeclarative/QDeclarativeExtensionPlugin>
 +#include <QtQml/QQmlExtensionPlugin>
  
 -class DialogPlugin : public QDeclarativeExtensionPlugin
 +class DialogPlugin : public QQmlExtensionPlugin
  {
      Q_OBJECT
 -    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "dialogplugin.json")
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "dialogplugin.json")
  
      public:
 -        //registerTypes is inherited from QDeclarativeExtensionPlugin
 +        //registerTypes is inherited from QQmlExtensionPlugin
          void registerTypes(const char *uri);
  
  };
index 0000000,4854256..2112ab8
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,58 +1,58 @@@
 -#include <QtDeclarative/QDeclarativeEngine>
 -#include <QtDeclarative/QDeclarativeComponent>
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
+ ** This file is part of the examples of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #include <QtGui/QGuiApplication>
 -    QDeclarativeEngine engine;
 -    QDeclarativeComponent component(&engine);
++#include <QtQml/QQmlEngine>
++#include <QtQml/QQmlComponent>
+ #include <QtCore/QUrl>
+ #include <QDebug>
+ int main(int argc, char* argv[])
+ {
+     QGuiApplication app(argc, argv);
++    QQmlEngine engine;
++    QQmlComponent component(&engine);
+     component.loadUrl(QUrl::fromLocalFile("Window.qml"));
+     if ( component.isReady() )
+         component.create();
+     else
+         qWarning() << component.errorString();
+     return app.exec();
+ }
index 0000000,74804bd..c451841
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,5 +1,5 @@@
 -QT += declarative
+ TEMPLATE = app
+ CONFIG += qt
++QT += qml
+ SOURCES += window.cpp
@@@ -2,12 -2,15 +2,15 @@@ TARGET  = qmlfolderlistmodelplugi
  TARGETPATH = Qt/labs/folderlistmodel
  include(../qimportbase.pri)
  
- QT += widgets qml
 -QT += declarative
++QT += qml
  
- SOURCES += qquickfolderlistmodel.cpp plugin.cpp
- HEADERS += qquickfolderlistmodel.h
 -SOURCES += qdeclarativefolderlistmodel.cpp plugin.cpp \
++SOURCES += qquickfolderlistmodel.cpp plugin.cpp \
+     fileinfothread.cpp
 -HEADERS += qdeclarativefolderlistmodel.h \
++HEADERS += qquickfolderlistmodel.h \
+     fileproperty_p.h \
+     fileinfothread_p.h
  
 -DESTDIR = $$QT.declarative.imports/$$TARGETPATH
 +DESTDIR = $$QT.qml.imports/$$TARGETPATH
  target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
  
  qmldir.files += $$PWD/qmldir
  QT_BEGIN_NAMESPACE
  
  //![class decl]
 -class QmlFolderListModelPlugin : public QDeclarativeExtensionPlugin
 +class QmlFolderListModelPlugin : public QQmlExtensionPlugin
  {
      Q_OBJECT
 -    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "folderlistmodel.json")
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "folderlistmodel.json")
  public:
      virtual void registerTypes(const char *uri)
      {
index 5621622,0000000..d68d7af
mode 100644,000000..100644
--- /dev/null
@@@ -1,529 -1,0 +1,697 @@@
- #include <QDirModel>
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the examples of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +//![code]
 +#include "qquickfolderlistmodel.h"
- #ifndef QT_NO_DIRMODEL
++#include "fileinfothread_p.h"
++#include "fileproperty_p.h"
 +#include <QDebug>
 +#include <qqmlcontext.h>
 +
-     QQuickFolderListModelPrivate()
-         : sortField(QQuickFolderListModel::Name), sortReversed(false), count(0), showDirs(true), showDots(false), showOnlyReadable(false), insideRefresh(false) {
 +QT_BEGIN_NAMESPACE
 +
 +class QQuickFolderListModelPrivate
 +{
++    Q_DECLARE_PUBLIC(QQuickFolderListModel)
++
 +public:
-     void updateSorting() {
-         QDir::SortFlags flags = 0;
-         switch(sortField) {
++    QQuickFolderListModelPrivate(QQuickFolderListModel *q)
++        : q_ptr(q),
++          sortField(QQuickFolderListModel::Name), sortReversed(false), showDirs(true), showDirsFirst(false), showDots(false), showOnlyReadable(false)
++    {
 +        nameFilters << QLatin1String("*");
 +    }
 +
-         }
++
++    QQuickFolderListModel *q_ptr;
++    QUrl currentDir;
++    QUrl rootDir;
++    FileInfoThread fileInfoThread;
++    QList<FileProperty> data;
++    QHash<int, QByteArray> roleNames;
++    QQuickFolderListModel::SortField sortField;
++    QStringList nameFilters;
++    bool sortReversed;
++    bool showDirs;
++    bool showDirsFirst;
++    bool showDots;
++    bool showOnlyReadable;
++
++    ~QQuickFolderListModelPrivate() {}
++    void init();
++    void updateSorting();
++
++    // private slots
++    void _q_directoryChanged(const QString &directory, const QList<FileProperty> &list);
++    void _q_directoryUpdated(const QString &directory, const QList<FileProperty> &list, int fromIndex, int toIndex);
++    void _q_sortFinished(const QList<FileProperty> &list);
++};
++
++
++void QQuickFolderListModelPrivate::init()
++{
++    Q_Q(QQuickFolderListModel);
++    qRegisterMetaType<QList<FileProperty> >("QList<FileProperty>");
++    q->connect(&fileInfoThread, SIGNAL(directoryChanged(QString, QList<FileProperty>)),
++               q, SLOT(_q_directoryChanged(QString, QList<FileProperty>)));
++    q->connect(&fileInfoThread, SIGNAL(directoryUpdated(QString, QList<FileProperty>, int, int)),
++               q, SLOT(_q_directoryUpdated(QString, QList<FileProperty>, int, int)));
++    q->connect(&fileInfoThread, SIGNAL(sortFinished(QList<FileProperty>)),
++               q, SLOT(_q_sortFinished(QList<FileProperty>)));
++}
++
++
++void QQuickFolderListModelPrivate::updateSorting()
++{
++    Q_Q(QQuickFolderListModel);
++
++    QDir::SortFlags flags = 0;
++
++    switch (sortField) {
 +        case QQuickFolderListModel::Unsorted:
 +            flags |= QDir::Unsorted;
 +            break;
 +        case QQuickFolderListModel::Name:
 +            flags |= QDir::Name;
 +            break;
 +        case QQuickFolderListModel::Time:
 +            flags |= QDir::Time;
 +            break;
 +        case QQuickFolderListModel::Size:
 +            flags |= QDir::Size;
 +            break;
 +        case QQuickFolderListModel::Type:
 +            flags |= QDir::Type;
 +            break;
-         if (sortReversed)
-             flags |= QDir::Reversed;
++        default:
++            break;
++    }
++
++    emit q->layoutAboutToBeChanged();
++
++    if (sortReversed)
++        flags |= QDir::Reversed;
++
++    fileInfoThread.setSortFlags(flags);
++}
++
++void QQuickFolderListModelPrivate::_q_directoryChanged(const QString &directory, const QList<FileProperty> &list)
++{
++    Q_Q(QQuickFolderListModel);
++    Q_UNUSED(directory);
++
++    data = list;
++    q->endResetModel();
++    emit q->rowCountChanged();
++    emit q->folderChanged();
++}
 +
-         model.setSorting(flags);
 +
-     QDirModel model;
-     QUrl folder;
-     QStringList nameFilters;
-     QModelIndex folderIndex;
-     QQuickFolderListModel::SortField sortField;
-     bool sortReversed;
-     int count;
-     bool showDirs;
-     bool showDots;
-     bool showOnlyReadable;
-     bool insideRefresh;
- };
++void QQuickFolderListModelPrivate::_q_directoryUpdated(const QString &directory, const QList<FileProperty> &list, int fromIndex, int toIndex)
++{
++    Q_Q(QQuickFolderListModel);
++    Q_UNUSED(directory);
++
++    QModelIndex parent;
++    if (data.size() > list.size()) {
++        //File(s) removed. Since I do not know how many
++        //or where I need to update the whole list from the first item.
++        data = list;
++        q->beginRemoveRows(parent, fromIndex, toIndex);
++        q->endRemoveRows();
++        q->beginInsertRows(parent, fromIndex, list.size()-1);
++        q->endInsertRows();
++        emit q->rowCountChanged();
++    } else if (data.size() < list.size()) {
++        //qDebug() << "File added. FromIndex: " << fromIndex << " toIndex: " << toIndex << " list size: " << list.size();
++        //File(s) added. Calculate how many and insert
++        //from the first changed one.
++        toIndex = fromIndex + (list.size() - data.size()-1);
++        q->beginInsertRows(parent, fromIndex, toIndex);
++        q->endInsertRows();
++        data = list;
++        emit q->rowCountChanged();
++        QModelIndex modelIndexFrom = q->createIndex(fromIndex, 0);
++        QModelIndex modelIndexTo = q->createIndex(toIndex, 0);
++        emit q->dataChanged(modelIndexFrom, modelIndexTo);
++    } else {
++        //qDebug() << "File has been updated";
++        QModelIndex modelIndexFrom = q->createIndex(fromIndex, 0);
++        QModelIndex modelIndexTo = q->createIndex(toIndex, 0);
++        data = list;
++        emit q->dataChanged(modelIndexFrom, modelIndexTo);
 +    }
++}
++
++void QQuickFolderListModelPrivate::_q_sortFinished(const QList<FileProperty> &list)
++{
++    Q_Q(QQuickFolderListModel);
++
++    QModelIndex parent;
++    q->beginRemoveRows(parent, 0, data.size()-1);
++    data.clear();
++    q->endRemoveRows();
++
++    q->beginInsertRows(parent, 0, list.size()-1);
++    data = list;
++    q->endInsertRows();
++}
 +
-     \o fileName
-     \o filePath
 +
 +/*!
 +    \qmlclass FolderListModel QQuickFolderListModel
 +    \ingroup qml-working-with-data
 +    \brief The FolderListModel provides a model of the contents of a file system folder.
 +
 +    FolderListModel provides access to information about the contents of a folder
 +    in the local file system, exposing a list of files to views and other data components.
 +
 +    \note This type is made available by importing the \c Qt.labs.folderlistmodel module.
 +    \e{Elements in the Qt.labs module are not guaranteed to remain compatible
 +    in future versions.}
 +
 +    \bold{import Qt.labs.folderlistmodel 1.0}
 +
 +    The \l folder property specifies the folder to access. Information about the
 +    files and directories in the folder is supplied via the model's interface.
 +    Components access names and paths via the following roles:
 +
 +    \list
-     : QAbstractListModel(parent)
++    \o \c fileName
++    \o \c filePath
++    \o \c fileBaseName
++    \o \c fileSuffix
++    \o \c fileSize
++    \o \c fileModified
++    \o \c fileAccessed
++    \o \c fileIsDir
 +    \endlist
 +
 +    Additionally a file entry can be differentiated from a folder entry via the
 +    isFolder() method.
 +
 +    \section1 Filtering
 +
 +    Various properties can be set to filter the number of files and directories
 +    exposed by the model.
 +
 +    The \l nameFilters property can be set to contain a list of wildcard filters
 +    that are applied to names of files and directories, causing only those that
 +    match the filters to be exposed.
 +
 +    Directories can be included or excluded using the \l showDirs property, and
 +    navigation directories can also be excluded by setting the \l showDotAndDotDot
 +    property to false.
 +
 +    It is sometimes useful to limit the files and directories exposed to those
 +    that the user can access. The \l showOnlyReadable property can be set to
 +    enable this feature.
 +
 +    \section1 Example Usage
 +
 +    The following example shows a FolderListModel being used to provide a list
 +    of QML files in a \l ListView:
 +
 +    \snippet doc/src/snippets/qml/folderlistmodel.qml 0
 +
 +    \section1 Path Separators
 +
 +    Qt uses "/" as a universal directory separator in the same way that "/" is
 +    used as a path separator in URLs. If you always use "/" as a directory
 +    separator, Qt will translate your paths to conform to the underlying
 +    operating system.
 +
 +    \sa {QML Data Models}
 +*/
 +
 +QQuickFolderListModel::QQuickFolderListModel(QObject *parent)
-     QHash<int, QByteArray> roles;
-     roles[FileNameRole] = "fileName";
-     roles[FilePathRole] = "filePath";
-     setRoleNames(roles);
-     d = new QQuickFolderListModelPrivate;
-     d->model.setFilter(QDir::AllDirs | QDir::Files | QDir::Drives | QDir::NoDotAndDotDot);
-     connect(&d->model, SIGNAL(rowsInserted(const QModelIndex&,int,int))
-             , this, SLOT(inserted(const QModelIndex&,int,int)));
-     connect(&d->model, SIGNAL(rowsRemoved(const QModelIndex&,int,int))
-             , this, SLOT(removed(const QModelIndex&,int,int)));
-     connect(&d->model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&))
-             , this, SLOT(handleDataChanged(const QModelIndex&,const QModelIndex&)));
-     connect(&d->model, SIGNAL(modelReset()), this, SLOT(refresh()));
-     connect(&d->model, SIGNAL(layoutChanged()), this, SLOT(refresh()));
++    : QAbstractListModel(parent), d_ptr(new QQuickFolderListModelPrivate(this))
 +{
-     delete d;
++    Q_D(QQuickFolderListModel);
++    d->roleNames[FileNameRole] = "fileName";
++    d->roleNames[FilePathRole] = "filePath";
++    d->roleNames[FileBaseNameRole] = "fileBaseName";
++    d->roleNames[FileSuffixRole] = "fileSuffix";
++    d->roleNames[FileSizeRole] = "fileSize";
++    d->roleNames[FileLastModifiedRole] = "fileModified";
++    d->roleNames[FileLastReadRole] = "fileAccessed";
++    d->roleNames[FileIsDirRole] = "fileIsDir";
++    setRoleNames(d->roleNames);
++
++    d->init();
 +}
 +
 +QQuickFolderListModel::~QQuickFolderListModel()
 +{
-     QModelIndex modelIndex = d->model.index(index.row(), 0, d->folderIndex);
-     if (modelIndex.isValid()) {
-         if (role == FileNameRole)
-             rv = d->model.data(modelIndex, QDirModel::FileNameRole).toString();
-         else if (role == FilePathRole)
-             rv = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString());
 +}
 +
 +QVariant QQuickFolderListModel::data(const QModelIndex &index, int role) const
 +{
++    Q_D(const QQuickFolderListModel);
 +    QVariant rv;
-     return d->count;
++
++    if (index.row() >= d->data.size())
++        return rv;
++
++    switch (role)
++    {
++        case FileNameRole:
++            rv = d->data.at(index.row()).fileName();
++            break;
++        case FilePathRole:
++            rv = d->data.at(index.row()).filePath();
++            break;
++        case FileBaseNameRole:
++            rv = d->data.at(index.row()).baseName();
++            break;
++        case FileSuffixRole:
++            rv = d->data.at(index.row()).suffix();
++            break;
++        case FileSizeRole:
++            rv = d->data.at(index.row()).size();
++            break;
++        case FileLastModifiedRole:
++            rv = d->data.at(index.row()).lastModified().date().toString(Qt::ISODate) + " " + d->data.at(index.row()).lastModified().time().toString();
++            break;
++        case FileLastReadRole:
++            rv = d->data.at(index.row()).lastRead().date().toString(Qt::ISODate) + " " + d->data.at(index.row()).lastRead().time().toString();
++            break;
++        case FileIsDirRole:
++            rv = d->data.at(index.row()).isDir();
++            break;
++        default:
++            break;
 +    }
 +    return rv;
 +}
 +
 +/*!
 +    \qmlproperty int FolderListModel::count
 +
 +    Returns the number of items in the current folder that match the
 +    filter criteria.
 +*/
 +int QQuickFolderListModel::rowCount(const QModelIndex &parent) const
 +{
++    Q_D(const QQuickFolderListModel);
 +    Q_UNUSED(parent);
-     return d->folder;
++    return d->data.size();
++}
++
++QModelIndex QQuickFolderListModel::index(int row, int , const QModelIndex &) const
++{
++    return createIndex(row, 0);
 +}
 +
 +/*!
 +    \qmlproperty string FolderListModel::folder
 +
 +    The \a folder property holds a URL for the folder that the model is
 +    currently providing.
 +
 +    The value is a URL expressed as a string, and must be a \c file: or \c qrc:
 +    URL, or a relative URL.
 +
 +    By default, the value is an invalid URL.
 +*/
 +QUrl QQuickFolderListModel::folder() const
 +{
-     if (folder == d->folder)
++    Q_D(const QQuickFolderListModel);
++    return d->currentDir;
 +}
 +
 +void QQuickFolderListModel::setFolder(const QUrl &folder)
 +{
-     QModelIndex index = d->model.index(folder.toLocalFile()); // This can modify the filtering rules.
-     if ((index.isValid() && d->model.isDir(index)) || folder.toLocalFile().isEmpty()) {
-         d->folder = folder;
-         QMetaObject::invokeMethod(this, "resetFiltering", Qt::QueuedConnection); // resetFiltering will invoke refresh().
-         emit folderChanged();
++    Q_D(QQuickFolderListModel);
++
++    if (folder == d->currentDir)
 +        return;
 +
- void QQuickFolderListModel::resetFiltering()
++    QString resolvedPath = QDir::cleanPath(folder.path());
++
++    beginResetModel();
++
++    //Remove the old path for the file system watcher
++    if (!d->currentDir.isEmpty())
++        d->fileInfoThread.removePath(d->currentDir.path());
++
++    d->currentDir = folder;
++
++    QFileInfo info(resolvedPath);
++    if (!info.exists() || !info.isDir()) {
++        d->data.clear();
++        endResetModel();
++        emit rowCountChanged();
++        return;
 +    }
++
++    d->fileInfoThread.setPath(resolvedPath);
++}
++
++
++/*!
++   \qmlproperty string QQuickFolderListModel::rootFolder
++
++   When the rootFolder is set, then this folder will
++   be threated as the root in the file system, so that
++   you can only travers sub folders from this rootFolder.
++*/
++QUrl QQuickFolderListModel::rootFolder() const
++{
++    Q_D(const QQuickFolderListModel);
++    return d->rootDir;
 +}
 +
-     // ensure that we reset the filtering rules, because the QDirModel::index()
-     // function isn't quite as const as it claims to be.
-     QDir::Filters filt = d->model.filter();
++void QQuickFolderListModel::setRootFolder(const QUrl &path)
 +{
-     if (d->showDirs)
-         filt |= (QDir::AllDirs | QDir::Drives);
-     else
-         filt &= ~(QDir::AllDirs | QDir::Drives);
++    Q_D(QQuickFolderListModel);
 +
-     if (d->showDots)
-         filt &= ~QDir::NoDotAndDotDot;
-     else
-         filt |= QDir::NoDotAndDotDot;
++    if (path.isEmpty())
++        return;
 +
-     if (d->showOnlyReadable)
-         filt |= QDir::Readable;
-     else
-         filt &= ~QDir::Readable;
++    QString resolvedPath = QDir::cleanPath(path.path());
 +
-     d->model.setFilter(filt); // this causes a refresh().
++    QFileInfo info(resolvedPath);
++    if (!info.exists() || !info.isDir())
++        return;
 +
-     QString localFile = d->folder.toLocalFile();
++    d->fileInfoThread.setRootPath(resolvedPath);
++    d->rootDir = path;
 +}
 +
++
 +/*!
 +    \qmlproperty url FolderListModel::parentFolder
 +
 +    Returns the URL of the parent of of the current \l folder.
 +*/
 +QUrl QQuickFolderListModel::parentFolder() const
 +{
-         int pos = d->folder.path().lastIndexOf(QLatin1Char('/'));
++    Q_D(const QQuickFolderListModel);
++
++    QString localFile = d->currentDir.toLocalFile();
 +    if (!localFile.isEmpty()) {
 +        QDir dir(localFile);
 +#if defined(Q_OS_WIN)
 +        if (dir.isRoot())
 +            dir.setPath("");
 +        else
 +#endif
 +            dir.cdUp();
 +        localFile = dir.path();
 +    } else {
-         localFile = d->folder.path().left(pos);
++        int pos = d->currentDir.path().lastIndexOf(QLatin1Char('/'));
 +        if (pos == -1)
 +            return QUrl();
-     d->model.setNameFilters(d->nameFilters);
++        localFile = d->currentDir.path().left(pos);
 +    }
 +    return QUrl::fromLocalFile(localFile);
 +}
 +
 +/*!
 +    \qmlproperty list<string> FolderListModel::nameFilters
 +
 +    The \a nameFilters property contains a list of file name filters.
 +    The filters may include the ? and * wildcards.
 +
 +    The example below filters on PNG and JPEG files:
 +
 +    \qml
 +    FolderListModel {
 +        nameFilters: [ "*.png", "*.jpg" ]
 +    }
 +    \endqml
 +
 +    \note Directories are not excluded by filters.
 +*/
 +QStringList QQuickFolderListModel::nameFilters() const
 +{
++    Q_D(const QQuickFolderListModel);
 +    return d->nameFilters;
 +}
 +
 +void QQuickFolderListModel::setNameFilters(const QStringList &filters)
 +{
++    Q_D(QQuickFolderListModel);
++    d->fileInfoThread.setNameFilters(filters);
 +    d->nameFilters = filters;
-     if (!d->folder.isValid() || d->folder.toLocalFile().isEmpty() || !QDir().exists(d->folder.toLocalFile()))
-         setFolder(QUrl(QLatin1String("file://")+QDir::currentPath()));
 +}
 +
 +void QQuickFolderListModel::classBegin()
 +{
 +}
 +
 +void QQuickFolderListModel::componentComplete()
 +{
-     if (!d->folderIndex.isValid())
-         QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
++    Q_D(QQuickFolderListModel);
 +
-     \o Unsorted - no sorting is applied.  The order is system default.
++    if (!d->currentDir.isValid() || d->currentDir.toLocalFile().isEmpty() || !QDir().exists(d->currentDir.toLocalFile()))
++        setFolder(QUrl(QLatin1String("file://")+QDir::currentPath()));
 +}
 +
 +/*!
 +    \qmlproperty enumeration FolderListModel::sortField
 +
 +    The \a sortField property contains field to use for sorting.  sortField
 +    may be one of:
 +    \list
-     \o Time - sort by time modified
++    \o Unsorted - no sorting is applied.
 +    \o Name - sort by filename
-         QModelIndex idx = d->model.index(index, 0, d->folderIndex);
-         if (idx.isValid())
-             return d->model.isDir(idx);
++    \o LastModified - sort by time modified
 +    \o Size - sort by file size
 +    \o Type - sort by file type (extension)
 +    \endlist
 +
 +    \sa sortReversed
 +*/
 +QQuickFolderListModel::SortField QQuickFolderListModel::sortField() const
 +{
++    Q_D(const QQuickFolderListModel);
 +    return d->sortField;
 +}
 +
 +void QQuickFolderListModel::setSortField(SortField field)
 +{
++    Q_D(QQuickFolderListModel);
 +    if (field != d->sortField) {
 +        d->sortField = field;
 +        d->updateSorting();
 +    }
 +}
 +
++int QQuickFolderListModel::roleFromString(const QString &roleName) const
++{
++    Q_D(const QQuickFolderListModel);
++    return d->roleNames.key(roleName.toLatin1(), -1);
++}
++
 +/*!
 +    \qmlproperty bool FolderListModel::sortReversed
 +
 +    If set to true, reverses the sort order.  The default is false.
 +
 +    \sa sortField
 +*/
 +bool QQuickFolderListModel::sortReversed() const
 +{
++    Q_D(const QQuickFolderListModel);
 +    return d->sortReversed;
 +}
 +
 +void QQuickFolderListModel::setSortReversed(bool rev)
 +{
++    Q_D(QQuickFolderListModel);
++
 +    if (rev != d->sortReversed) {
 +        d->sortReversed = rev;
 +        d->updateSorting();
 +    }
 +}
 +
 +/*!
 +    \qmlmethod bool FolderListModel::isFolder(int index)
 +
 +    Returns true if the entry \a index is a folder; otherwise
 +    returns false.
 +*/
 +bool QQuickFolderListModel::isFolder(int index) const
 +{
 +    if (index != -1) {
- void QQuickFolderListModel::refresh()
- {
-     if (d->insideRefresh)
-         return;
-     d->insideRefresh = true;
++        QModelIndex idx = createIndex(index, 0);
++        if (idx.isValid()) {
++            QVariant var = data(idx, FileIsDirRole);
++            if (var.isValid())
++                return var.toBool();
++        }
 +    }
 +    return false;
 +}
 +
-     d->folderIndex = QModelIndex();
-     if (d->count) {
-         emit beginRemoveRows(QModelIndex(), 0, d->count-1);
-         d->count = 0;
-         emit endRemoveRows();
-     }
++/*!
++    \qmlproperty bool FolderListModel::showDirs
 +
-     d->folderIndex = d->model.index(d->folder.toLocalFile());
-     int newcount = d->model.rowCount(d->folderIndex);
-     if (newcount) {
-         emit beginInsertRows(QModelIndex(), 0, newcount-1);
-         d->count = newcount;
-         emit endInsertRows();
-     }
++    If true, directories are included in the model; otherwise only files
++    are included.
 +
-     d->insideRefresh = false; // finished refreshing.
- }
++    By default, this property is true.
 +
- void QQuickFolderListModel::inserted(const QModelIndex &index, int start, int end)
++    Note that the nameFilters are not applied to directories.
 +
-     if (index == d->folderIndex) {
-         emit beginInsertRows(QModelIndex(), start, end);
-         d->count = d->model.rowCount(d->folderIndex);
-         emit endInsertRows();
-     }
++    \sa showDotAndDotDot
++*/
++bool QQuickFolderListModel::showDirs() const
 +{
- void QQuickFolderListModel::removed(const QModelIndex &index, int start, int end)
++    Q_D(const QQuickFolderListModel);
++    return d->showDirs;
 +}
 +
-     if (index == d->folderIndex) {
-         emit beginRemoveRows(QModelIndex(), start, end);
-         d->count = d->model.rowCount(d->folderIndex);
-         emit endRemoveRows();
-     }
- }
++void  QQuickFolderListModel::setShowDirs(bool on)
 +{
- void QQuickFolderListModel::handleDataChanged(const QModelIndex &start, const QModelIndex &end)
- {
-     if (start.parent() == d->folderIndex)
-         emit dataChanged(index(start.row(),0), index(end.row(),0));
++    Q_D(QQuickFolderListModel);
 +
-     \qmlproperty bool FolderListModel::showDirs
++    d->fileInfoThread.setShowDirs(on);
++    d->showDirs = on;
 +}
 +
 +/*!
-     If true, directories are included in the model; otherwise only files
-     are included.
++    \qmlproperty bool FolderListModel::showDirsFirst
 +
-     By default, this property is true.
-     Note that the nameFilters are not applied to directories.
++    If true, if directories are included in the model they will
++    always be shown first, then the files.
 +
-     \sa showDotAndDotDot
++    By default, this property is false.
 +
- bool QQuickFolderListModel::showDirs() const
 +*/
-     return d->model.filter() & QDir::AllDirs;
++bool QQuickFolderListModel::showDirsFirst() const
 +{
- void  QQuickFolderListModel::setShowDirs(bool on)
++    Q_D(const QQuickFolderListModel);
++    return d->showDirsFirst;
 +}
 +
-     if (!(d->model.filter() & QDir::AllDirs) == !on)
-         return;
-     if (on) {
-         d->showDirs = true;
-         d->model.setFilter(d->model.filter() | QDir::AllDirs | QDir::Drives);
-     } else {
-         d->showDirs = false;
-         d->model.setFilter(d->model.filter() & ~(QDir::AllDirs | QDir::Drives));
-     }
++void  QQuickFolderListModel::setShowDirsFirst(bool on)
 +{
-     return !(d->model.filter() & QDir::NoDotAndDotDot);
++    Q_D(QQuickFolderListModel);
++
++    d->fileInfoThread.setShowDirsFirst(on);
++    d->showDirsFirst = on;
 +}
 +
++
 +/*!
 +    \qmlproperty bool FolderListModel::showDotAndDotDot
 +
 +    If true, the "." and ".." directories are included in the model; otherwise
 +    they are excluded.
 +
 +    By default, this property is false.
 +
 +    \sa showDirs
 +*/
 +bool QQuickFolderListModel::showDotAndDotDot() const
 +{
-     if (!(d->model.filter() & QDir::NoDotAndDotDot) == on)
-         return;
-     if (on) {
-         d->showDots = true;
-         d->model.setFilter(d->model.filter() & ~QDir::NoDotAndDotDot);
-     } else {
-         d->showDots = false;
-         d->model.setFilter(d->model.filter() | QDir::NoDotAndDotDot);
++    Q_D(const QQuickFolderListModel);
++    return d->showDots;
 +}
 +
 +void  QQuickFolderListModel::setShowDotAndDotDot(bool on)
 +{
-     return d->model.filter() & QDir::Readable;
++    Q_D(QQuickFolderListModel);
++
++    if (on != d->showDots) {
++        d->fileInfoThread.setShowDotDot(on);
 +    }
 +}
 +
 +/*!
 +    \qmlproperty bool FolderListModel::showOnlyReadable
 +
 +    If true, only readable files and directories are shown; otherwise all files
 +    and directories are shown.
 +
 +    By default, this property is false.
 +
 +    \sa showDirs
 +*/
 +bool QQuickFolderListModel::showOnlyReadable() const
 +{
-     if (!(d->model.filter() & QDir::Readable) == !on)
-         return;
-     if (on) {
-         d->showOnlyReadable = true;
-         d->model.setFilter(d->model.filter() | QDir::Readable);
-     } else {
-         d->showOnlyReadable = false;
-         d->model.setFilter(d->model.filter() & ~QDir::Readable);
++    Q_D(const QQuickFolderListModel);
++    return d->showOnlyReadable;
 +}
 +
 +void QQuickFolderListModel::setShowOnlyReadable(bool on)
 +{
- #endif // QT_NO_DIRMODEL
++    Q_D(QQuickFolderListModel);
++
++    if (on != d->showOnlyReadable) {
++        d->fileInfoThread.setShowOnlyReadable(on);
 +    }
 +}
 +
++/*!
++    \qmlmethod QVariant QQuickFolderListModel::get(int idx, const QString &property) const
++
++    Get the folder property for the given index. The following properties
++    are available.
++
++    \list
++        \o \c fileName
++        \o \c filePath
++        \o \c fileBaseName
++        \o \c fileSuffix
++        \o \c fileSize
++        \o \c fileModified
++        \o \c fileAccessed
++        \o \c fileIsDir
++    \endlist
++*/
++QVariant QQuickFolderListModel::get(int idx, const QString &property) const
++{
++    int role = roleFromString(property);
++    if (role >= 0 && idx >= 0)
++        return data(index(idx, 0), role);
++    else
++        return QVariant();
++}
++
++#include "moc_qquickfolderlistmodel.cpp"
++
 +//![code]
 +QT_END_NAMESPACE
index 10af7c8,0000000..830a30b
mode 100644,000000..100644
--- /dev/null
@@@ -1,159 -1,0 +1,169 @@@
- #ifndef QT_NO_DIRMODEL
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the examples of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQUICKFOLDERLISTMODEL_H
 +#define QQUICKFOLDERLISTMODEL_H
 +
 +#include <qqml.h>
 +#include <QStringList>
 +#include <QUrl>
 +#include <QAbstractListModel>
 +
-     Q_PROPERTY(int count READ count)
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class QQmlContext;
 +class QModelIndex;
 +
 +class QQuickFolderListModelPrivate;
 +
 +//![class begin]
 +class QQuickFolderListModel : public QAbstractListModel, public QQmlParserStatus
 +{
 +    Q_OBJECT
 +    Q_INTERFACES(QQmlParserStatus)
 +//![class begin]
 +
 +//![class props]
 +    Q_PROPERTY(QUrl folder READ folder WRITE setFolder NOTIFY folderChanged)
++    Q_PROPERTY(QUrl rootFolder READ rootFolder WRITE setRootFolder)
 +    Q_PROPERTY(QUrl parentFolder READ parentFolder NOTIFY folderChanged)
 +    Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters)
 +    Q_PROPERTY(SortField sortField READ sortField WRITE setSortField)
 +    Q_PROPERTY(bool sortReversed READ sortReversed WRITE setSortReversed)
 +    Q_PROPERTY(bool showDirs READ showDirs WRITE setShowDirs)
++    Q_PROPERTY(bool showDirsFirst READ showDirsFirst WRITE setShowDirsFirst)
 +    Q_PROPERTY(bool showDotAndDotDot READ showDotAndDotDot WRITE setShowDotAndDotDot)
 +    Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable)
-     enum Roles { FileNameRole = Qt::UserRole+1, FilePathRole = Qt::UserRole+2 };
-     int rowCount(const QModelIndex &parent) const;
-     QVariant data(const QModelIndex &index, int role) const;
++    Q_PROPERTY(int count READ count NOTIFY rowCountChanged)
 +//![class props]
 +
 +//![abslistmodel]
 +public:
 +    QQuickFolderListModel(QObject *parent = 0);
 +    ~QQuickFolderListModel();
 +
-     void  setShowDirs(bool);
++    enum Roles {
++        FileNameRole = Qt::UserRole + 1,
++        FilePathRole = Qt::UserRole + 2,
++        FileBaseNameRole = Qt::UserRole + 3,
++        FileSuffixRole = Qt::UserRole + 4,
++        FileSizeRole = Qt::UserRole + 5,
++        FileLastModifiedRole = Qt::UserRole + 6,
++        FileLastReadRole = Qt::UserRole +7,
++        FileIsDirRole = Qt::UserRole + 8
++    };
++
++    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
++    virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
++    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
 +//![abslistmodel]
 +
 +//![count]
 +    int count() const { return rowCount(QModelIndex()); }
 +//![count]
 +
 +//![prop funcs]
 +    QUrl folder() const;
 +    void setFolder(const QUrl &folder);
++    QUrl rootFolder() const;
++    void setRootFolder(const QUrl &path);
 +
 +    QUrl parentFolder() const;
 +
 +    QStringList nameFilters() const;
 +    void setNameFilters(const QStringList &filters);
 +
 +    enum SortField { Unsorted, Name, Time, Size, Type };
 +    SortField sortField() const;
 +    void setSortField(SortField field);
 +    Q_ENUMS(SortField)
 +
 +    bool sortReversed() const;
 +    void setSortReversed(bool rev);
 +
 +    bool showDirs() const;
-     void  setShowDotAndDotDot(bool);
++    void setShowDirs(bool showDirs);
++    bool showDirsFirst() const;
++    void setShowDirsFirst(bool showDirsFirst);
 +    bool showDotAndDotDot() const;
-     void  setShowOnlyReadable(bool);
++    void setShowDotAndDotDot(bool on);
 +    bool showOnlyReadable() const;
- //![isfolder]
++    void setShowOnlyReadable(bool on);
 +//![prop funcs]
 +
- //![isfolder]
 +    Q_INVOKABLE bool isFolder(int index) const;
- private Q_SLOTS:
-     void refresh();
-     void resetFiltering();
-     void inserted(const QModelIndex &index, int start, int end);
-     void removed(const QModelIndex &index, int start, int end);
-     void handleDataChanged(const QModelIndex &start, const QModelIndex &end);
++    Q_INVOKABLE QVariant get(int idx, const QString &property) const;
 +
 +//![parserstatus]
 +    virtual void classBegin();
 +    virtual void componentComplete();
 +//![parserstatus]
 +
++    int roleFromString(const QString &roleName) const;
++
 +//![notifier]
 +Q_SIGNALS:
 +    void folderChanged();
++    void rowCountChanged() const;
 +//![notifier]
 +
 +//![class end]
-     QQuickFolderListModelPrivate *d;
++
 +
 +private:
 +    Q_DISABLE_COPY(QQuickFolderListModel)
- //![qml decl]
- QML_DECLARE_TYPE(QQuickFolderListModel)
- //![qml decl]
++    Q_DECLARE_PRIVATE(QQuickFolderListModel)
++    QScopedPointer<QQuickFolderListModelPrivate> d_ptr;
++
++    Q_PRIVATE_SLOT(d_func(), void _q_directoryChanged(const QString &directory, const QList<FileProperty> &list))
++    Q_PRIVATE_SLOT(d_func(), void _q_directoryUpdated(const QString &directory, const QList<FileProperty> &list, int fromIndex, int toIndex))
++    Q_PRIVATE_SLOT(d_func(), void _q_sortFinished(const QList<FileProperty> &list))
 +};
 +//![class end]
 +
 +QT_END_NAMESPACE
 +
- #endif // QT_NO_DIRMODEL
 +QT_END_HEADER
 +
 +#endif // QQUICKFOLDERLISTMODEL_H
@@@ -6,7 -6,9 +6,9 @@@ QT += sql qml qml-private v8-private co
  
  SOURCES += plugin.cpp
  
 -DESTDIR = $$QT.declarative.imports/$$TARGETPATH
+ OTHER_FILES += localstorage.json
 +DESTDIR = $$QT.qml.imports/$$TARGETPATH
  target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
  
  qmldir.files += $$PWD/qmldir
@@@ -648,11 -648,13 +648,13 @@@ static QObject *module_api_factory(QQml
     return api;
  }
  
 -class QDeclarativeLocalStoragePlugin : public QDeclarativeExtensionPlugin
 +class QQmlLocalStoragePlugin : public QQmlExtensionPlugin
  {
      Q_OBJECT
 -    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "localstorage.json")
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "localstorage.json")
  public:
 -    QDeclarativeLocalStoragePlugin()
 +    QQmlLocalStoragePlugin()
      {
      }
  
@@@ -132,9 -132,11 +132,11 @@@ QML_DECLARE_TYPE(QuickTestUtil
  
  QT_BEGIN_NAMESPACE
  
 -class QTestQmlModule : public QDeclarativeExtensionPlugin
 +class QTestQmlModule : public QQmlExtensionPlugin
  {
      Q_OBJECT
 -    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "testlib.json")
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "testlib.json")
  public:
      virtual void registerTypes(const char *uri)
      {
@@@ -4,12 -4,13 +4,13 @@@ include(../qimportbase.pri
  
  CONFIG += qt plugin
  
 -QT += declarative quick qmltest qmltest-private v8-private declarative-private core-private testlib
 +QT += qml quick qmltest qmltest-private v8-private qml-private core-private testlib
  
  SOURCES += main.cpp
- HEADERS +=
+ OTHER_FILES += testlib.json
  
 -DESTDIR = $$QT.declarative.imports/$$TARGETPATH
 +DESTDIR = $$QT.qml.imports/$$TARGETPATH
  
  target.path += $$[QT_INSTALL_IMPORTS]/QtTest
  OTHER_IMPORT_FILES = \
  
  QT_BEGIN_NAMESPACE
  
 -class QmlXmlListModelPlugin : public QDeclarativeExtensionPlugin
 +class QmlXmlListModelPlugin : public QQmlExtensionPlugin
  {
      Q_OBJECT
 -    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeExtensionInterface" FILE "xmllistmodel.json")
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "xmllistmodel.json")
  public:
      virtual void registerTypes(const char *uri)
      {
Simple merge
@@@ -24,8 -24,10 +24,10 @@@ HEADERS += 
      qquickviewinspector.h \
      ../shared/abstracttool.h \
      ../shared/abstractviewinspector.h \
 -    ../shared/qdeclarativeinspectorprotocol.h \
 +    ../shared/qqmlinspectorprotocol.h \
      ../shared/qmlinspectorconstants.h
  
+ OTHER_FILES += qtquick2plugin.json
  target.path += $$[QT_INSTALL_PLUGINS]/qmltooling
  INSTALLS += target
@@@ -55,7 -55,8 +55,8 @@@ class QtQuick2Plugin : public QObject, 
  {
      Q_OBJECT
      Q_DISABLE_COPY(QtQuick2Plugin)
 -    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeInspectorInterface" FILE "qtquick2plugin.json")
 -    Q_INTERFACES(QDeclarativeInspectorInterface)
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlInspectorInterface" FILE "qtquick2plugin.json")
 +    Q_INTERFACES(QQmlInspectorInterface)
  
  public:
      QtQuick2Plugin();
@@@ -190,10 -190,8 +190,8 @@@ void QTcpServerConnection::newConnectio
  
  void QTcpServerConnection::invalidPacket()
  {
 -    qWarning("QDeclarativeDebugServer: Received a corrupted packet! Giving up ...");
 +    qWarning("QQmlDebugServer: Received a corrupted packet! Giving up ...");
  }
  
- Q_EXPORT_PLUGIN2(tcpserver, QTcpServerConnection)
  QT_END_NAMESPACE
  
@@@ -54,9 -54,9 +54,9 @@@ class QTcpServerConnection : public QOb
      Q_OBJECT
      Q_DECLARE_PRIVATE(QTcpServerConnection)
      Q_DISABLE_COPY(QTcpServerConnection)
 -    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDeclarativeDebugServerConnection" FILE "qtcpserverconnection.json")
 -    Q_INTERFACES(QDeclarativeDebugServerConnection)
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlDebugServerConnection" FILE "qtcpserverconnection.json")
 +    Q_INTERFACES(QQmlDebugServerConnection)
  
  public:
      QTcpServerConnection();
      ~QTcpServerConnection();
index 2c52809,0000000..dcaa514
mode 100644,000000..100644
--- /dev/null
@@@ -1,124 -1,0 +1,126 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qdebugmessageservice_p.h"
 +#include "qqmldebugservice_p_p.h"
 +
++#include <QDataStream>
++
 +QT_BEGIN_NAMESPACE
 +
 +Q_GLOBAL_STATIC(QDebugMessageService, qmlDebugMessageService)
 +
 +void DebugMessageHandler(QtMsgType type, const QMessageLogContext &ctxt,
 +                         const char *buf)
 +{
 +    QDebugMessageService::instance()->sendDebugMessage(type, ctxt, buf);
 +}
 +
 +class QDebugMessageServicePrivate : public QQmlDebugServicePrivate
 +{
 +public:
 +    QDebugMessageServicePrivate()
 +        : oldMsgHandler(0)
 +        , prevState(QQmlDebugService::NotConnected)
 +    {
 +    }
 +
 +    QMessageHandler oldMsgHandler;
 +    QQmlDebugService::State prevState;
 +};
 +
 +QDebugMessageService::QDebugMessageService(QObject *parent) :
 +    QQmlDebugService(*(new QDebugMessageServicePrivate()),
 +                                   QLatin1String("DebugMessages"), 2, parent)
 +{
 +    Q_D(QDebugMessageService);
 +
 +    registerService();
 +    if (state() == Enabled) {
 +        d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
 +        d->prevState = Enabled;
 +    }
 +}
 +
 +QDebugMessageService *QDebugMessageService::instance()
 +{
 +    return qmlDebugMessageService();
 +}
 +
 +void QDebugMessageService::sendDebugMessage(QtMsgType type,
 +                                            const QMessageLogContext &ctxt,
 +                                            const char *buf)
 +{
 +    Q_D(QDebugMessageService);
 +
 +    //We do not want to alter the message handling mechanism
 +    //We just eavesdrop and forward the messages to a port
 +    //only if a client is connected to it.
 +    QByteArray message;
 +    QDataStream ws(&message, QIODevice::WriteOnly);
 +    ws << QByteArray("MESSAGE") << type << QString::fromLocal8Bit(buf).toUtf8();
 +    ws << QString::fromLatin1(ctxt.file).toUtf8();
 +    ws << ctxt.line << QString::fromLatin1(ctxt.function).toUtf8();
 +
 +    sendMessage(message);
 +    if (d->oldMsgHandler)
 +        (*d->oldMsgHandler)(type, ctxt, buf);
 +}
 +
 +void QDebugMessageService::stateChanged(State state)
 +{
 +    Q_D(QDebugMessageService);
 +
 +    if (state != Enabled && d->prevState == Enabled) {
 +        QMessageHandler handler = qInstallMessageHandler(d->oldMsgHandler);
 +        // has our handler been overwritten in between?
 +        if (handler != DebugMessageHandler)
 +            qInstallMessageHandler(handler);
 +
 +    } else if (state == Enabled && d->prevState != Enabled) {
 +        d->oldMsgHandler = qInstallMessageHandler(DebugMessageHandler);
 +
 +    }
 +
 +    d->prevState = state;
 +}
 +
 +QT_END_NAMESPACE
index c9092f1,0000000..ab9e7bd
mode 100644,000000..100644
--- /dev/null
@@@ -1,85 -1,0 +1,87 @@@
- #include <QtCore/QtPlugin>
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLDEBUGSERVERCONNECTION_H
 +#define QQMLDEBUGSERVERCONNECTION_H
 +
 +#include <QtQml/qtqmlglobal.h>
- Q_DECLARE_INTERFACE(QQmlDebugServerConnection, "com.trolltech.Qt.QQmlDebugServerConnection/1.0")
++#include <private/qqmlglobal_p.h>
 +
 +//
 +//  W A R N I N G
 +//  -------------
 +//
 +// This file is not part of the Qt API.  It exists purely as an
 +// implementation detail.  This header file may change from version to
 +// version without notice, or even be removed.
 +//
 +// We mean it.
 +//
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class QQmlDebugServer;
 +class Q_QML_EXPORT QQmlDebugServerConnection
 +{
 +public:
 +    QQmlDebugServerConnection() {}
 +    virtual ~QQmlDebugServerConnection() {}
 +
 +    virtual void setServer(QQmlDebugServer *server) = 0;
 +    virtual void setPort(int port, bool bock) = 0;
 +    virtual bool isConnected() const = 0;
 +    virtual void send(const QList<QByteArray> &messages) = 0;
 +    virtual void disconnect() = 0;
 +    virtual bool waitForMessage() = 0;
 +};
 +
++#define QQmlDebugServerConnection_iid "org.qt-project.Qt.QQmlDebugServerConnection"
++
++Q_DECLARE_INTERFACE(QQmlDebugServerConnection, QQmlDebugServerConnection_iid)
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QQMLDEBUGSERVERCONNECTION_H
index 7f52dff,0000000..5b015d3
mode 100644,000000..100644
--- /dev/null
@@@ -1,83 -1,0 +1,86 @@@
- Q_DECLARE_INTERFACE(QQmlInspectorInterface, "com.trolltech.Qt.QQmlInspectorInterface/1.0")
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLINSPECTORINTERFACE_H
 +#define QQMLINSPECTORINTERFACE_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 <QtQml/qtqmlglobal.h>
++#include <private/qqmlglobal_p.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class Q_QML_EXPORT QQmlInspectorInterface
 +{
 +public:
 +    QQmlInspectorInterface() {}
 +    virtual ~QQmlInspectorInterface() {}
 +
 +    virtual bool canHandleView(QObject *view) = 0;
 +
 +    virtual void activate(QObject *view) = 0;
 +    virtual void deactivate() = 0;
 +
 +    virtual void clientMessage(const QByteArray &message) = 0;
 +};
 +
++#define QQmlInspectorInterface_iid "org.qt-project.Qt.QQmlInspectorInterface"
++
++Q_DECLARE_INTERFACE(QQmlInspectorInterface, QQmlInspectorInterface_iid)
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QQMLINSPECTORINTERFACE_H
index d6a0307,0000000..2731d20
mode 100644,000000..100644
--- /dev/null
@@@ -1,357 -1,0 +1,315 @@@
- QQmlBindingProfiler::QQmlBindingProfiler(const QString &url, int line, int column)
- {
-     QQmlProfilerService::startRange(QQmlProfilerService::Binding);
-     QQmlProfilerService::rangeLocation(QQmlProfilerService::Binding, url, line, column);
- }
- QQmlBindingProfiler::~QQmlBindingProfiler()
- {
-     QQmlProfilerService::endRange(QQmlProfilerService::Binding);
- }
- void QQmlBindingProfiler::addDetail(const QString &details)
- {
-     QQmlProfilerService::rangeData(QQmlProfilerService::Binding, details);
- }
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlprofilerservice_p.h"
 +
 +#include <QtCore/qdatastream.h>
 +#include <QtCore/qurl.h>
 +#include <QtCore/qtimer.h>
 +#include <QtCore/qthread.h>
 +#include <QtCore/qcoreapplication.h>
 +
 +// this contains QUnifiedTimer
 +#include <private/qabstractanimation_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
++// instance will be set, unset in constructor. Allows static methods to be inlined.
++QQmlProfilerService *QQmlProfilerService::instance = 0;
 +Q_GLOBAL_STATIC(QQmlProfilerService, profilerInstance)
 +
-     profilerInstance();
 +
 +// convert to a QByteArray that can be sent to the debug client
 +// use of QDataStream can skew results
 +//     (see tst_qqmldebugtrace::trace() benchmark)
 +QByteArray QQmlProfilerData::toByteArray() const
 +{
 +    QByteArray data;
 +    //### using QDataStream is relatively expensive
 +    QDataStream ds(&data, QIODevice::WriteOnly);
 +    ds << time << messageType << detailType;
 +    if (messageType == (int)QQmlProfilerService::RangeData)
 +        ds << detailData;
 +    if (messageType == (int)QQmlProfilerService::RangeLocation)
 +        ds << detailData << line << column;
 +    if (messageType == (int)QQmlProfilerService::Event &&
 +            detailType == (int)QQmlProfilerService::AnimationFrame)
 +        ds << framerate << animationcount;
 +    return data;
 +}
 +
 +QQmlProfilerService::QQmlProfilerService()
 +    : QQmlDebugService(QLatin1String("CanvasFrameRate"), 1),
 +      m_enabled(false), m_messageReceived(false)
 +{
 +    m_timer.start();
 +
 +    if (registerService() == Enabled) {
 +        // wait for first message indicating whether to trace or not
 +        while (!m_messageReceived)
 +            waitForMessage();
 +
 +        QUnifiedTimer::instance()->registerProfilerCallback( &animationFrame );
 +    }
 +}
 +
 +QQmlProfilerService::~QQmlProfilerService()
 +{
++    instance = 0;
 +}
 +
 +void QQmlProfilerService::initialize()
 +{
 +    // just make sure that the service is properly registered
- void QQmlProfilerService::startRange(RangeType t)
- {
-     profilerInstance()->startRangeImpl(t);
- }
- void QQmlProfilerService::rangeData(RangeType t, const QString &data)
- {
-     profilerInstance()->rangeDataImpl(t, data);
- }
- void QQmlProfilerService::rangeData(RangeType t, const QUrl &data)
- {
-     profilerInstance()->rangeDataImpl(t, data);
- }
- void QQmlProfilerService::rangeLocation(RangeType t, const QString &fileName, int line, int column)
- {
-     profilerInstance()->rangeLocationImpl(t, fileName, line, column);
- }
- void QQmlProfilerService::rangeLocation(RangeType t, const QUrl &fileName, int line, int column)
- {
-     profilerInstance()->rangeLocationImpl(t, fileName, line, column);
- }
- void QQmlProfilerService::endRange(RangeType t)
- {
-     profilerInstance()->endRangeImpl(t);
- }
++    instance = profilerInstance();
 +}
 +
 +bool QQmlProfilerService::startProfiling()
 +{
 +    return profilerInstance()->startProfilingImpl();
 +}
 +
 +bool QQmlProfilerService::stopProfiling()
 +{
 +    return profilerInstance()->stopProfilingImpl();
 +}
 +
 +void QQmlProfilerService::sendStartedProfilingMessage()
 +{
 +    profilerInstance()->sendStartedProfilingMessageImpl();
 +}
 +
 +void QQmlProfilerService::addEvent(EventType t)
 +{
 +    profilerInstance()->addEventImpl(t);
 +}
 +
- void QQmlProfilerService::startRangeImpl(RangeType range)
 +void QQmlProfilerService::animationFrame(qint64 delta)
 +{
 +    profilerInstance()->animationFrameImpl(delta);
 +}
 +
 +void QQmlProfilerService::sendProfilingData()
 +{
 +    profilerInstance()->sendMessages();
 +}
 +
 +bool QQmlProfilerService::startProfilingImpl()
 +{
 +    bool success = false;
 +    if (!profilingEnabled()) {
 +        setProfilingEnabled(true);
 +        sendStartedProfilingMessageImpl();
 +        success = true;
 +    }
 +    return success;
 +}
 +
 +bool QQmlProfilerService::stopProfilingImpl()
 +{
 +    bool success = false;
 +    if (profilingEnabled()) {
 +        addEventImpl(EndTrace);
 +        setProfilingEnabled(false);
 +        success = true;
 +    }
 +    return success;
 +}
 +
 +void QQmlProfilerService::sendStartedProfilingMessageImpl()
 +{
 +    if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
 +        return;
 +
 +    QQmlProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)StartTrace, QString(), -1, -1, 0, 0};
 +    QQmlDebugService::sendMessage(ed.toByteArray());
 +}
 +
 +void QQmlProfilerService::addEventImpl(EventType event)
 +{
 +    if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
 +        return;
 +
 +    QQmlProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event, QString(), -1, -1, 0, 0};
 +    processMessage(ed);
 +}
 +
- void QQmlProfilerService::rangeDataImpl(RangeType range, const QString &rData)
++void QQmlProfilerService::startRange(RangeType range)
 +{
 +    if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
 +        return;
 +
 +    QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range, QString(), -1, -1, 0, 0};
 +    processMessage(rd);
 +}
 +
- void QQmlProfilerService::rangeDataImpl(RangeType range, const QUrl &rData)
++void QQmlProfilerService::rangeData(RangeType range, const QString &rData)
 +{
 +    if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
 +        return;
 +
 +    QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData, -1, -1, 0, 0};
 +    processMessage(rd);
 +}
 +
- void QQmlProfilerService::rangeLocationImpl(RangeType range, const QString &fileName, int line, int column)
++void QQmlProfilerService::rangeData(RangeType range, const QUrl &rData)
 +{
 +    if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
 +        return;
 +
 +    QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1, -1, 0, 0};
 +    processMessage(rd);
 +}
 +
- void QQmlProfilerService::rangeLocationImpl(RangeType range, const QUrl &fileName, int line, int column)
++void QQmlProfilerService::rangeLocation(RangeType range, const QString &fileName, int line, int column)
 +{
 +    if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
 +        return;
 +
 +    QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName, line, column, 0, 0};
 +    processMessage(rd);
 +}
 +
- void QQmlProfilerService::endRangeImpl(RangeType range)
++void QQmlProfilerService::rangeLocation(RangeType range, const QUrl &fileName, int line, int column)
 +{
 +    if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
 +        return;
 +
 +    QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line, column, 0, 0};
 +    processMessage(rd);
 +}
 +
++void QQmlProfilerService::endRange(RangeType range)
 +{
 +    if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
 +        return;
 +
 +    QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range, QString(), -1, -1, 0, 0};
 +    processMessage(rd);
 +}
 +
 +void QQmlProfilerService::animationFrameImpl(qint64 delta)
 +{
 +    Q_ASSERT(QQmlDebugService::isDebuggingEnabled());
 +    if (!m_enabled)
 +        return;
 +
 +    int animCount = QUnifiedTimer::instance()->runningAnimationCount();
 +
 +    if (animCount > 0 && delta > 0) {
 +        // trim fps to integer
 +        int fps = 1000 / delta;
 +        QQmlProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)AnimationFrame, QString(), -1, -1, fps, animCount};
 +        processMessage(ed);
 +    }
 +}
 +
 +/*
 +    Either send the message directly, or queue up
 +    a list of messages to send later (via sendMessages)
 +*/
 +void QQmlProfilerService::processMessage(const QQmlProfilerData &message)
 +{
 +    QMutexLocker locker(&m_mutex);
 +    m_data.append(message);
 +}
 +
 +bool QQmlProfilerService::profilingEnabled()
 +{
 +    return m_enabled;
 +}
 +
 +void QQmlProfilerService::setProfilingEnabled(bool enable)
 +{
 +    m_enabled = enable;
 +}
 +
 +/*
 +    Send the messages queued up by processMessage
 +*/
 +void QQmlProfilerService::sendMessages()
 +{
 +    QMutexLocker locker(&m_mutex);
 +    QList<QByteArray> messages;
 +    for (int i = 0; i < m_data.count(); ++i)
 +        messages << m_data.at(i).toByteArray();
 +    m_data.clear();
 +
 +    //indicate completion
 +    QByteArray data;
 +    QDataStream ds(&data, QIODevice::WriteOnly);
 +    ds << (qint64)-1 << (int)Complete;
 +    messages << data;
 +
 +    QQmlDebugService::sendMessages(messages);
 +}
 +
 +void QQmlProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
 +{
 +    if (state() == newState)
 +        return;
 +
 +    if (state() == Enabled
 +            && m_enabled) {
 +        stopProfilingImpl();
 +        sendMessages();
 +    }
 +}
 +
 +void QQmlProfilerService::messageReceived(const QByteArray &message)
 +{
 +    QByteArray rwData = message;
 +    QDataStream stream(&rwData, QIODevice::ReadOnly);
 +
 +    bool enabled;
 +    stream >> enabled;
 +
 +    m_messageReceived = true;
 +
 +    if (enabled) {
 +        startProfilingImpl();
 +    } else {
 +        if (stopProfilingImpl())
 +            sendMessages();
 +    }
 +}
 +
 +QT_END_NAMESPACE
index a74ce10,0000000..7a70845
mode 100644,000000..100644
--- /dev/null
@@@ -1,183 -1,0 +1,303 @@@
- // RAII
- class Q_AUTOTEST_EXPORT QQmlBindingProfiler {
- public:
-     QQmlBindingProfiler(const QString &url, int line, int column);
-     ~QQmlBindingProfiler();
-     void addDetail(const QString &details);
- };
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLPROFILERSERVICE_P_H
 +#define QQMLPROFILERSERVICE_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/qqmldebugservice_p.h>
++#include <QtQml/qtqmlglobal.h>
 +#include <QtCore/qelapsedtimer.h>
 +#include <QtCore/qmutex.h>
 +#include <QtCore/qvector.h>
++#include <QtCore/qstringbuilder.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +struct Q_AUTOTEST_EXPORT QQmlProfilerData
 +{
 +    qint64 time;
 +    int messageType;
 +    int detailType;
 +
 +    //###
 +    QString detailData; //used by RangeData and RangeLocation
 +    int line;           //used by RangeLocation
 +    int column;         //used by RangeLocation
 +    int framerate;      //used by animation events
 +    int animationcount; //used by animation events
 +
 +    QByteArray toByteArray() const;
 +};
 +
 +Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
 +
 +class QUrl;
 +class QQmlEngine;
 +
-     static void startRange(RangeType);
-     static void rangeData(RangeType, const QString &);
-     static void rangeData(RangeType, const QUrl &);
-     static void rangeLocation(RangeType, const QString &, int, int);
-     static void rangeLocation(RangeType, const QUrl &, int, int);
-     static void endRange(RangeType);
 +
 +class Q_QML_EXPORT QQmlProfilerService : public QQmlDebugService
 +{
 +public:
 +    enum Message {
 +        Event,
 +        RangeStart,
 +        RangeData,
 +        RangeLocation,
 +        RangeEnd,
 +        Complete, // end of transmission
 +
 +        MaximumMessage
 +    };
 +
 +    enum EventType {
 +        FramePaint,
 +        Mouse,
 +        Key,
 +        AnimationFrame,
 +        EndTrace,
 +        StartTrace,
 +
 +        MaximumEventType
 +    };
 +
 +    enum RangeType {
 +        Painting,
 +        Compiling,
 +        Creating,
 +        Binding,            //running a binding
 +        HandlingSignal,     //running a signal handler
 +
 +        MaximumRangeType
 +    };
 +
 +    static void initialize();
 +
 +    static bool startProfiling();
 +    static bool stopProfiling();
 +    static void sendStartedProfilingMessage();
 +    static void addEvent(EventType);
-     void startRangeImpl(RangeType);
-     void rangeDataImpl(RangeType, const QString &);
-     void rangeDataImpl(RangeType, const QUrl &);
-     void rangeLocationImpl(RangeType, const QString &, int, int);
-     void rangeLocationImpl(RangeType, const QUrl &, int, int);
-     void endRangeImpl(RangeType);
 +    static void animationFrame(qint64);
 +
 +    static void sendProfilingData();
 +
 +    QQmlProfilerService();
 +    ~QQmlProfilerService();
 +
 +protected:
 +    virtual void stateAboutToBeChanged(State state);
 +    virtual void messageReceived(const QByteArray &);
 +
 +private:
 +    bool startProfilingImpl();
 +    bool stopProfilingImpl();
 +    void sendStartedProfilingMessageImpl();
 +    void addEventImpl(EventType);
 +    void animationFrameImpl(qint64);
 +
++    void startRange(RangeType);
++    void rangeData(RangeType, const QString &);
++    void rangeData(RangeType, const QUrl &);
++    void rangeLocation(RangeType, const QString &, int, int);
++    void rangeLocation(RangeType, const QUrl &, int, int);
++    void endRange(RangeType);
++
++
 +    bool profilingEnabled();
 +    void setProfilingEnabled(bool enable);
 +    void sendMessages();
 +    void processMessage(const QQmlProfilerData &);
 +
 +private:
 +    QElapsedTimer m_timer;
 +    bool m_enabled;
 +    bool m_messageReceived;
 +    QVector<QQmlProfilerData> m_data;
 +    QMutex m_mutex;
++
++    static QQmlProfilerService *instance;
++
++    friend struct QQmlBindingProfiler;
++    friend struct QQmlHandlingSignalProfiler;
++    friend struct QQmlObjectCreatingProfiler;
++    friend struct QQmlCompilingProfiler;
++};
++
++//
++// RAII helper structs
++//
++
++struct QQmlBindingProfiler {
++    QQmlBindingProfiler(const QString &url, int line, int column)
++    {
++        QQmlProfilerService *instance = QQmlProfilerService::instance;
++        enabled = instance ? instance->profilingEnabled() : false;
++        if (enabled) {
++            instance->startRange(QQmlProfilerService::Binding);
++            instance->rangeLocation(QQmlProfilerService::Binding, url, line, column);
++        }
++    }
++
++    ~QQmlBindingProfiler()
++    {
++        if (enabled)
++            QQmlProfilerService::instance->endRange(QQmlProfilerService::Binding);
++    }
++
++    void addDetail(const QString &details)
++    {
++        if (enabled)
++            QQmlProfilerService::instance->rangeData(QQmlProfilerService::Binding,
++                                                             details);
++    }
++\
++    bool enabled;
++};
++
++struct QQmlHandlingSignalProfiler {
++    QQmlHandlingSignalProfiler()
++    {
++        enabled = QQmlProfilerService::instance
++                ? QQmlProfilerService::instance->profilingEnabled() : false;
++        if (enabled) {
++            QQmlProfilerService::instance->startRange(
++                        QQmlProfilerService::HandlingSignal);
++        }
++    }
++
++    void setSignalInfo(const QString &name, const QString &expression)
++    {
++        if (enabled)
++            QQmlProfilerService::instance->rangeData(
++                        QQmlProfilerService::HandlingSignal,
++                        name % QLatin1String(": ") % expression);
++    }
++
++    void setLocation(const QString &file, int line, int column)
++    {
++        if (enabled)
++            QQmlProfilerService::instance->rangeLocation(
++                        QQmlProfilerService::HandlingSignal, file, line, column);
++    }
++
++    ~QQmlHandlingSignalProfiler()
++    {
++        if (enabled)
++            QQmlProfilerService::instance->endRange(
++                        QQmlProfilerService::HandlingSignal);
++    }
++
++    bool enabled;
++};
++
++struct QQmlObjectCreatingProfiler {
++    QQmlObjectCreatingProfiler()
++    {
++        QQmlProfilerService *instance = QQmlProfilerService::instance;
++        enabled = instance ?
++                    instance->profilingEnabled() : false;
++        if (enabled)
++            instance->startRange(QQmlProfilerService::Creating);
++    }
++
++    void setTypeName(const QString &typeName)
++    {
++        if (enabled)
++            QQmlProfilerService::instance->rangeData(
++                        QQmlProfilerService::Creating, typeName);
++    }
++
++    void setLocation(const QUrl &url, int line, int column)
++    {
++        if (enabled)
++            QQmlProfilerService::instance->rangeLocation(
++                        QQmlProfilerService::Creating, url, line, column);
++    }
++
++    ~QQmlObjectCreatingProfiler()
++    {
++        if (enabled)
++            QQmlProfilerService::instance->endRange(QQmlProfilerService::Creating);
++    }
++
++    bool enabled;
++};
++
++struct QQmlCompilingProfiler {
++    QQmlCompilingProfiler(const QString &name)
++    {
++        QQmlProfilerService *instance = QQmlProfilerService::instance;
++        enabled = instance ?
++                    instance->profilingEnabled() : false;
++        if (enabled) {
++            instance->startRange(QQmlProfilerService::Compiling);
++            instance->rangeLocation(QQmlProfilerService::Compiling, name, 1, 1);
++            instance->rangeData(QQmlProfilerService::Compiling, name);
++        }
++    }
++
++    ~QQmlCompilingProfiler()
++    {
++        if (enabled)
++            QQmlProfilerService::instance->endRange(QQmlProfilerService::Compiling);
++    }
++
++    bool enabled;
 +};
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QQMLPROFILERSERVICE_P_H
 +
index eba8b0f,0000000..6473a2f
mode 100644,000000..100644
--- /dev/null
@@@ -1,287 -1,0 +1,301 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qv8profilerservice_p.h"
 +#include "qqmldebugservice_p_p.h"
 +#include "private/qjsconverter_impl_p.h"
 +#include <private/qv8profiler_p.h>
 +
 +#include <QtCore/QHash>
 +
 +QT_BEGIN_NAMESPACE
 +
 +Q_GLOBAL_STATIC(QV8ProfilerService, v8ProfilerInstance)
 +
 +class DebugServiceOutputStream : public v8::OutputStream
 +{
 +    QQmlDebugService &_service;
 +public:
 +    DebugServiceOutputStream(QQmlDebugService &service)
 +        : v8::OutputStream(),
 +          _service(service) {}
 +    void EndOfStream() {}
 +    WriteResult WriteAsciiChunk(char *rawData, int size)
 +    {
 +        QByteArray data;
 +        QDataStream ds(&data, QIODevice::WriteOnly);
 +        ds << QV8ProfilerService::V8SnapshotChunk << QByteArray(rawData, size);
 +        _service.sendMessage(data);
 +        return kContinue;
 +    }
 +};
 +
 +// convert to a QByteArray that can be sent to the debug client
 +QByteArray QV8ProfilerData::toByteArray() const
 +{
 +    QByteArray data;
 +    //### using QDataStream is relatively expensive
 +    QDataStream ds(&data, QIODevice::WriteOnly);
 +    ds << messageType << filename << functionname << lineNumber << totalTime << selfTime << treeLevel;
 +
 +    return data;
 +}
 +
 +class QV8ProfilerServicePrivate : public QQmlDebugServicePrivate
 +{
 +    Q_DECLARE_PUBLIC(QV8ProfilerService)
 +
 +public:
 +    QV8ProfilerServicePrivate()
 +        :initialized(false)
 +    {
 +    }
 +
 +    void takeSnapshot(v8::HeapSnapshot::Type);
 +
 +    void printProfileTree(const v8::CpuProfileNode *node, int level = 0);
 +    void sendMessages();
 +
 +    QList<QV8ProfilerData> m_data;
 +
 +    bool initialized;
 +    QList<QString> m_ongoing;
 +};
 +
 +QV8ProfilerService::QV8ProfilerService(QObject *parent)
 +    : QQmlDebugService(*(new QV8ProfilerServicePrivate()), QLatin1String("V8Profiler"), 1, parent)
 +{
 +    Q_D(QV8ProfilerService);
 +
 +    if (registerService() == Enabled) {
 +        // ,block mode, client attached
 +        while (!d->initialized)
 +            waitForMessage();
 +    }
 +}
 +
 +QV8ProfilerService::~QV8ProfilerService()
 +{
 +}
 +
 +QV8ProfilerService *QV8ProfilerService::instance()
 +{
 +    return v8ProfilerInstance();
 +}
 +
 +void QV8ProfilerService::initialize()
 +{
 +    // just make sure that the service is properly registered
 +    v8ProfilerInstance();
 +}
 +
 +void QV8ProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
 +{
 +    Q_D(QV8ProfilerService);
 +
 +    if (state() == newState)
 +        return;
 +
 +    if (state() == Enabled) {
 +        foreach (const QString &title, d->m_ongoing)
 +            QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, title));
 +        sendProfilingData();
 +    }
 +}
 +
 +void QV8ProfilerService::messageReceived(const QByteArray &message)
 +{
 +    Q_D(QV8ProfilerService);
 +
 +    QDataStream ds(message);
 +    QByteArray command;
 +    QByteArray option;
 +    QByteArray title;
 +    ds >> command >> option;
 +
 +    if (command == "V8PROFILER") {
 +        ds >>  title;
 +        QString titleStr = QString::fromUtf8(title);
 +        if (option == "start") {
 +            QMetaObject::invokeMethod(this, "startProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr));
 +        } else if (option == "stop" && d->initialized) {
 +            QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr));
 +            QMetaObject::invokeMethod(this, "sendProfilingData", Qt::QueuedConnection);
 +        }
 +        d->initialized = true;
 +    }
 +
 +    if (command == "V8SNAPSHOT") {
 +        if (option == "full")
 +            QMetaObject::invokeMethod(this, "takeSnapshot", Qt::QueuedConnection);
 +        else if (option == "delete") {
 +            QMetaObject::invokeMethod(this, "deleteSnapshots", Qt::QueuedConnection);
 +        }
 +    }
 +
 +    QQmlDebugService::messageReceived(message);
 +}
 +
 +void QV8ProfilerService::startProfiling(const QString &title)
 +{
 +    Q_D(QV8ProfilerService);
 +    // Start Profiling
 +
 +    if (d->m_ongoing.contains(title))
 +        return;
 +
 +    v8::HandleScope handle_scope;
 +    v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
 +    v8::CpuProfiler::StartProfiling(v8title);
 +
 +    d->m_ongoing.append(title);
++
++    // indicate profiling started
++    QByteArray data;
++    QDataStream ds(&data, QIODevice::WriteOnly);
++    ds << (int)QV8ProfilerService::V8Started;
++
++    sendMessage(data);
 +}
 +
 +void QV8ProfilerService::stopProfiling(const QString &title)
 +{
 +    Q_D(QV8ProfilerService);
 +    // Stop profiling
 +
 +    if (!d->m_ongoing.contains(title))
 +        return;
 +    d->m_ongoing.removeOne(title);
 +
 +    v8::HandleScope handle_scope;
 +    v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
 +    const v8::CpuProfile *cpuProfile = v8::CpuProfiler::StopProfiling(v8title);
 +    if (cpuProfile) {
 +        // can happen at start
 +        const v8::CpuProfileNode *rootNode = cpuProfile->GetTopDownRoot();
 +        d->printProfileTree(rootNode);
++    } else {
++        // indicate completion, even without data
++        QByteArray data;
++        QDataStream ds(&data, QIODevice::WriteOnly);
++        ds << (int)QV8ProfilerService::V8Complete;
++
++        sendMessage(data);
 +    }
 +}
 +
 +void QV8ProfilerService::takeSnapshot()
 +{
 +    Q_D(QV8ProfilerService);
 +    d->takeSnapshot(v8::HeapSnapshot::kFull);
 +}
 +
 +void QV8ProfilerService::deleteSnapshots()
 +{
 +    v8::HeapProfiler::DeleteAllSnapshots();
 +}
 +
 +void QV8ProfilerService::sendProfilingData()
 +{
 +    Q_D(QV8ProfilerService);
 +    // Send messages to client
 +    d->sendMessages();
 +}
 +
 +void QV8ProfilerServicePrivate::printProfileTree(const v8::CpuProfileNode *node, int level)
 +{
 +    for (int index = 0 ; index < node->GetChildrenCount() ; index++) {
 +        const v8::CpuProfileNode* childNode = node->GetChild(index);
 +        QString scriptResourceName = QJSConverter::toString(childNode->GetScriptResourceName());
 +        if (scriptResourceName.length() > 0) {
 +
 +            QV8ProfilerData rd = {(int)QV8ProfilerService::V8Entry, scriptResourceName,
 +                QJSConverter::toString(childNode->GetFunctionName()),
 +                childNode->GetLineNumber(), childNode->GetTotalTime(), childNode->GetSelfTime(), level};
 +            m_data.append(rd);
 +
 +            // different nodes might have common children: fix at client side
 +            if (childNode->GetChildrenCount() > 0) {
 +                printProfileTree(childNode, level+1);
 +            }
 +        }
 +    }
 +}
 +
 +void QV8ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType)
 +{
 +    Q_Q(QV8ProfilerService);
 +
 +    v8::HandleScope scope;
 +    v8::Local<v8::String> title = v8::String::New("");
 +
 +    DebugServiceOutputStream outputStream(*q);
 +    const v8::HeapSnapshot *snapshot = v8::HeapProfiler::TakeSnapshot(title, snapshotType);
 +    snapshot->Serialize(&outputStream, v8::HeapSnapshot::kJSON);
 +
 +    //indicate completion
 +    QByteArray data;
 +    QDataStream ds(&data, QIODevice::WriteOnly);
 +    ds << (int)QV8ProfilerService::V8SnapshotComplete;
 +
 +    q->sendMessage(data);
 +}
 +
 +void QV8ProfilerServicePrivate::sendMessages()
 +{
 +    Q_Q(QV8ProfilerService);
 +
 +    QList<QByteArray> messages;
 +    for (int i = 0; i < m_data.count(); ++i)
 +        messages << m_data.at(i).toByteArray();
 +    q->sendMessages(messages);
 +    m_data.clear();
 +
 +    //indicate completion
 +    QByteArray data;
 +    QDataStream ds(&data, QIODevice::WriteOnly);
 +    ds << (int)QV8ProfilerService::V8Complete;
 +
 +    q->sendMessage(data);
 +}
 +
 +
 +QT_END_NAMESPACE
index d408d9e,0000000..b706d17
mode 100644,000000..100644
--- /dev/null
@@@ -1,119 -1,0 +1,120 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QV8PROFILERSERVICE_P_H
 +#define QV8PROFILERSERVICE_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/qqmldebugservice_p.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +struct Q_AUTOTEST_EXPORT QV8ProfilerData
 +{
 +    int messageType;
 +    QString filename;
 +    QString functionname;
 +    int lineNumber;
 +    double totalTime;
 +    double selfTime;
 +    int treeLevel;
 +
 +    QByteArray toByteArray() const;
 +};
 +
 +class QQmlEngine;
 +class QV8ProfilerServicePrivate;
 +
 +class Q_AUTOTEST_EXPORT QV8ProfilerService : public QQmlDebugService
 +{
 +    Q_OBJECT
 +public:
 +    enum MessageType {
 +        V8Entry,
 +        V8Complete,
 +        V8SnapshotChunk,
 +        V8SnapshotComplete,
++        V8Started,
 +
 +        V8MaximumMessage
 +    };
 +
 +    QV8ProfilerService(QObject *parent = 0);
 +    ~QV8ProfilerService();
 +
 +    static QV8ProfilerService *instance();
 +    static void initialize();
 +
 +public slots:
 +    void startProfiling(const QString &title);
 +    void stopProfiling(const QString &title);
 +    void takeSnapshot();
 +    void deleteSnapshots();
 +
 +    void sendProfilingData();
 +
 +protected:
 +    void stateAboutToBeChanged(State state);
 +    void messageReceived(const QByteArray &);
 +
 +private:
 +    Q_DISABLE_COPY(QV8ProfilerService)
 +    Q_DECLARE_PRIVATE(QV8ProfilerService)
 +};
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QV8PROFILERSERVICE_P_H
index 9663c1e,0000000..02f5091
mode 100644,000000..100644
--- /dev/null
@@@ -1,369 -1,0 +1,313 @@@
- struct QMetaObjectPrivate 
- {
-     int revision;
-     int className;
-     int classInfoCount, classInfoData;
-     int methodCount, methodData;
-     int propertyCount, propertyData;
-     int enumeratorCount, enumeratorData;
-     int constructorCount, constructorData; //since revision 2
-     int flags; //since revision 3
-     int signalCount; //since revision 4
- };
- enum MetaObjectFlag {
-     DynamicMetaObject = 0x01
- };
- enum PropertyFlags  {
-     Invalid = 0x00000000,
-     Readable = 0x00000001,
-     Writable = 0x00000002,
-     Resettable = 0x00000004,
-     EnumOrFlag = 0x00000008,
-     StdCppSet = 0x00000100,
- //     Override = 0x00000200,
-     Constant = 0x00000400,
-     Final = 0x00000800,
-     Designable = 0x00001000,
-     ResolveDesignable = 0x00002000,
-     Scriptable = 0x00004000,
-     ResolveScriptable = 0x00008000,
-     Stored = 0x00010000,
-     ResolveStored = 0x00020000,
-     Editable = 0x00040000,
-     ResolveEditable = 0x00080000,
-     User = 0x00100000,
-     ResolveUser = 0x00200000,
-     Notify = 0x00400000,
-     Revisioned = 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,
-     MethodRevisioned = 0x80
- };
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qfastmetabuilder_p.h"
 +
 +#include <QtCore/qmetaobject.h>
++#include <private/qobject_p.h>
++#include <private/qmetaobject_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +struct QFastMetaBuilderHeader
 +{
 +    int fieldCount;
 +};
 +
-     p->revision = 4;
 +#define FMBHEADER_FIELD_COUNT 1
 +
 +#define HEADER_FIELD_COUNT 14
 +#define CLASSINFO_FIELD_COUNT 2
 +#define METHOD_FIELD_COUNT 5
 +#define PROPERTY_FIELD_COUNT 3
 +#define PROPERTY_NOTIFY_FIELD_COUNT 1
 +
 +static inline uint *fieldPointer(QByteArray &data)
 +{ return reinterpret_cast<uint *>(data.data()) + FMBHEADER_FIELD_COUNT; }
 +
 +static inline const uint *fieldPointer(const QByteArray &data)
 +{ return reinterpret_cast<const uint *>(data.constData()) + FMBHEADER_FIELD_COUNT; }
 +
 +static inline QMetaObjectPrivate *priv(QByteArray &data)
 +{ return reinterpret_cast<QMetaObjectPrivate*>(fieldPointer(data)); }
 +
 +static inline const QMetaObjectPrivate *priv(const QByteArray &data)
 +{ return reinterpret_cast<const QMetaObjectPrivate*>(fieldPointer(data)); }
 +
 +static inline QFastMetaBuilderHeader *header(QByteArray &data)
 +{ return reinterpret_cast<QFastMetaBuilderHeader*>(data.data()); }
 +
 +static inline const QFastMetaBuilderHeader *header(const QByteArray &data)
 +{ return reinterpret_cast<const QFastMetaBuilderHeader*>(data.constData()); }
 +
 +QFastMetaBuilder::QFastMetaBuilder()
 +: m_zeroPtr(0), m_stringData(0), m_stringDataLength(0), m_stringDataAllocated(0)
 +{
 +}
 +
 +QFastMetaBuilder::~QFastMetaBuilder()
 +{
 +}
 +
 +QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
 +                                                   int propertyCount, int methodCount, 
 +                                                   int signalCount, int classInfoCount)
 +{
 +    Q_ASSERT(m_data.isEmpty());
 +    Q_ASSERT(classNameLength > 0);
 +    Q_ASSERT(propertyCount >= 0);
 +    Q_ASSERT(methodCount >= 0);
 +    Q_ASSERT(signalCount >= 0);
 +    Q_ASSERT(classInfoCount >= 0);
 +
 +    int fieldCount = FMBHEADER_FIELD_COUNT +
 +                     HEADER_FIELD_COUNT + 
 +                     propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT) +
 +                     methodCount * (METHOD_FIELD_COUNT) +
 +                     signalCount * (METHOD_FIELD_COUNT) +
 +                     classInfoCount * CLASSINFO_FIELD_COUNT;
 +
 +    m_data.resize(fieldCount * sizeof(uint) + classNameLength + 1);
 +    m_stringData = m_data.data() + m_data.size() - classNameLength - 1;
 +    m_stringDataLength = classNameLength + 1;
 +    m_stringDataAllocated = classNameLength + 1;
 +    m_stringData[classNameLength] = 0;
 +    m_zeroPtr = classNameLength;
 +
 +    header(m_data)->fieldCount = fieldCount;
 +
 +    QMetaObjectPrivate *p = priv(m_data);
 +
 +    int dataIndex = HEADER_FIELD_COUNT;
 +
++    p->revision = 6;
 +    p->className = 0;
 +
 +    // Class infos
 +    p->classInfoCount = classInfoCount;
 +    if (p->classInfoCount) { 
 +        p->classInfoData = dataIndex;
 +        dataIndex += p->classInfoCount * CLASSINFO_FIELD_COUNT;
 +    } else {
 +        p->classInfoData = 0;
 +    }
 +
 +    // Methods
 +    p->methodCount = methodCount + signalCount;
 +    if (p->methodCount) {
 +        p->methodData = dataIndex;
 +        dataIndex += p->methodCount * METHOD_FIELD_COUNT;
 +    } else {
 +        p->methodData = 0;
 +    }
 +    p->signalCount = signalCount;
 +
 +    // Properties
 +    p->propertyCount = propertyCount;
 +    if (p->propertyCount) {
 +        p->propertyData = dataIndex;
 +        dataIndex += p->propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT);
 +    } else {
 +        p->propertyData = 0;
 +    }
 +
 +    // Flags
 +    p->flags = DynamicMetaObject; // Always dynamic
 +
 +    // Enums and constructors not supported
 +    p->enumeratorCount = 0;
 +    p->enumeratorData = 0;
 +    p->constructorCount = 0;
 +    p->constructorData = 0;
 +
 +    StringRef className;
 +    className._b = this;
 +    className._o = 0;
 +    className._l = classNameLength;
 +    return className;
 +}
 +
 +// Allocate a string of \a length.  \a length should *not* include the null terminator.
 +QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length)
 +{
 +    Q_ASSERT(length > 0);
 +
 +    StringRef sr;
 +    sr._b = this;
 +    sr._o = m_stringDataLength;
 +    sr._l = length;
 +
 +    m_stringDataLength += length + 1 /* for null terminator */;
 +
 +    return sr;
 +}
 +
 +void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const StringRef &value)
 +{
 +    Q_ASSERT(!m_data.isEmpty());
 +    Q_ASSERT(!key.isEmpty() && !value.isEmpty());
 +
 +    QMetaObjectPrivate *p = priv(m_data);
 +    Q_ASSERT(index < p->classInfoCount);
 +
 +    uint *ptr = fieldPointer(m_data) + p->classInfoData + index * CLASSINFO_FIELD_COUNT;
 +    // classinfo: key, value
 +    ptr[0] = key.offset(); ptr[1] = value.offset();
 +}
 +
 +void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type, 
 +                                   QMetaType::Type mtype, PropertyFlag flags, int notifySignal)
 +{
 +    Q_ASSERT(!m_data.isEmpty());
 +    Q_ASSERT(!name.isEmpty() && !type.isEmpty());
 +
 +    QMetaObjectPrivate *p = priv(m_data);
 +    Q_ASSERT(index < p->propertyCount);
 +
 +    uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
 +    // properties: name, type, flags
 +    ptr[0] = name.offset();
 +    ptr[1] = type.offset();
 +    if (notifySignal == -1) {
 +        ptr[2] = mtype << 24;
 +        ptr[2] |= flags | Scriptable | Readable;
 +        *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
 +    } else {
 +        ptr[2] = mtype << 24;
 +        ptr[2] |= flags | Scriptable | Readable | Notify;
 +        *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
 +    }
 +}
 +
 +void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type, 
 +                                   QFastMetaBuilder::PropertyFlag flags, int notifySignal)
 +{
 +    Q_ASSERT(!m_data.isEmpty());
 +    Q_ASSERT(!name.isEmpty() && !type.isEmpty());
 +
 +    QMetaObjectPrivate *p = priv(m_data);
 +    Q_ASSERT(index < p->propertyCount);
 +
 +    uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
 +    // properties: name, type, flags
 +    ptr[0] = name.offset();
 +    ptr[1] = type.offset();
 +    if (notifySignal == -1) {
 +        ptr[2] = flags | Scriptable | Readable;
 +        *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
 +    } else {
 +        ptr[2] = flags | Scriptable | Readable | Notify;
 +        *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
 +    }
 +}
 +
 +void QFastMetaBuilder::setSignal(int index, const StringRef &signature,
 +                                 const StringRef &parameterNames,
 +                                 const StringRef &type)
 +{
 +    Q_ASSERT(!m_data.isEmpty());
 +    Q_ASSERT(!signature.isEmpty());
 +
 +    QMetaObjectPrivate *p = priv(m_data);
 +    int mindex = metaObjectIndexForSignal(index);
 +
 +    uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
 +    // methods: signature, parameters, type, tag, flags
 +    ptr[0] = signature.offset();
 +    ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
 +    ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
 +    ptr[3] = m_zeroPtr;
 +    ptr[4] = AccessProtected | MethodSignal;
 +}
 +
 +void QFastMetaBuilder::setMethod(int index, const StringRef &signature,
 +                                 const StringRef &parameterNames,
 +                                 const StringRef &type)
 +{
 +    Q_ASSERT(!m_data.isEmpty());
 +    Q_ASSERT(!signature.isEmpty());
 +
 +    QMetaObjectPrivate *p = priv(m_data);
 +    int mindex = metaObjectIndexForMethod(index);
 +
 +    uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
 +    // methods: signature, parameters, type, tag, flags
 +    ptr[0] = signature.offset();
 +    ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
 +    ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
 +    ptr[3] = m_zeroPtr;
 +    ptr[4] = AccessProtected | MethodSlot;
 +}
 +
 +int QFastMetaBuilder::metaObjectIndexForSignal(int index) const
 +{
 +    Q_ASSERT(!m_data.isEmpty());
 +    Q_ASSERT(index < priv(m_data)->signalCount);
 +    return index;
 +}
 +
 +int QFastMetaBuilder::metaObjectIndexForMethod(int index) const
 +{
 +    Q_ASSERT(!m_data.isEmpty());
 +
 +    const QMetaObjectPrivate *p = priv(m_data);
 +    Q_ASSERT(index < (p->methodCount - p->signalCount));
 +    return index + p->signalCount;
 +}
 +
 +void QFastMetaBuilder::allocateStringData()
 +{
 +    if (m_stringDataAllocated < m_stringDataLength) {
 +        m_data.resize(m_data.size() + m_stringDataLength - m_stringDataAllocated);
 +        m_stringDataAllocated = m_stringDataLength;
 +        m_stringData = m_data.data() + header(m_data)->fieldCount * sizeof(uint);
 +    }
 +}
 +
 +void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data)
 +{
 +    output->d.superdata = parent;
 +    output->d.stringdata = data.constData() + header(data)->fieldCount * sizeof(uint);
 +    output->d.data = fieldPointer(data);
++    output->d.extradata = 0;
 +}
 +
 +QT_END_NAMESPACE
index 6f55245,0000000..ca6b13e
mode 100644,000000..100644
--- /dev/null
@@@ -1,300 -1,0 +1,305 @@@
-         if (QQmlDebugService::isDebuggingEnabled()) {
-             QQmlProfilerService::startRange(QQmlProfilerService::HandlingSignal);
-             QQmlProfilerService::rangeData(QQmlProfilerService::HandlingSignal, QLatin1String(m_signal.signature()) % QLatin1String(": ") % m_expression->expression());
-             QQmlProfilerService::rangeLocation(QQmlProfilerService::HandlingSignal, m_expression->sourceFile(), m_expression->lineNumber(), m_expression->columnNumber());
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlboundsignal_p.h"
 +
 +#include <private/qmetaobjectbuilder_p.h>
 +#include "qqmlengine_p.h"
 +#include "qqmlexpression_p.h"
 +#include "qqmlcontext_p.h"
 +#include "qqmlmetatype_p.h"
 +#include "qqml.h"
 +#include "qqmlcontext.h"
 +#include "qqmlglobal_p.h"
 +#include <private/qqmlprofilerservice_p.h>
 +#include <private/qv8debugservice_p.h>
 +
 +#include <QtCore/qstringbuilder.h>
 +#include <QtCore/qdebug.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QQmlBoundSignalParameters : public QObject
 +{
 +Q_OBJECT
 +public:
 +    QQmlBoundSignalParameters(const QMetaMethod &, QObject * = 0);
 +    ~QQmlBoundSignalParameters();
 +
 +    void setValues(void **);
 +    void clearValues();
 +
 +private:
 +    friend class MetaObject;
 +    int metaCall(QMetaObject::Call, int _id, void **);
 +    struct MetaObject : public QAbstractDynamicMetaObject {
 +        MetaObject(QQmlBoundSignalParameters *b)
 +            : parent(b) {}
 +
 +        int metaCall(QMetaObject::Call c, int id, void **a) { 
 +            return parent->metaCall(c, id, a);
 +        }
 +        QQmlBoundSignalParameters *parent;
 +    };
 +
 +    int *types;
 +    void **values;
 +    QMetaObject *myMetaObject;
 +};
 +
 +static int evaluateIdx = -1;
 +
 +QQmlAbstractBoundSignal::QQmlAbstractBoundSignal(QObject *parent)
 +: QObject(parent)
 +{
 +}
 +
 +QQmlAbstractBoundSignal::~QQmlAbstractBoundSignal()
 +{
 +}
 +
 +QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal, 
 +                               QObject *parent)
 +: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0)
 +{
 +    // 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 = metaObject()->methodCount();
 +
 +    QQml_setParent_noEvent(this, parent);
 +    QQmlPropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
 +}
 +
 +QQmlBoundSignal::QQmlBoundSignal(QQmlContext *ctxt, const QString &val, 
 +                               QObject *scope, const QMetaMethod &signal,
 +                               QObject *parent)
 +: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0)
 +{
 +    // 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 = metaObject()->methodCount();
 +
 +    QQml_setParent_noEvent(this, parent);
 +    QQmlPropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
 +
 +    m_expression = new QQmlExpression(ctxt, scope, val);
 +}
 +
 +QQmlBoundSignal::~QQmlBoundSignal()
 +{
 +    delete m_expression;
 +    m_expression = 0;
 +}
 +
 +int QQmlBoundSignal::index() const 
 +{ 
 +    return m_signal.methodIndex();
 +}
 +
 +/*!
 +    Returns the signal expression.
 +*/
 +QQmlExpression *QQmlBoundSignal::expression() const
 +{
 +    return m_expression;
 +}
 +
 +/*!
 +    Sets the signal expression to \a e.  Returns the current signal expression,
 +    or null if there is no signal expression.
 +
 +    The QQmlBoundSignal instance takes ownership of \a e.  The caller is 
 +    assumes ownership of the returned QQmlExpression.
 +*/
 +QQmlExpression *QQmlBoundSignal::setExpression(QQmlExpression *e)
 +{
 +    QQmlExpression *rv = m_expression;
 +    m_expression = e;
 +    if (m_expression) m_expression->setNotifyOnValueChanged(false);
 +    return rv;
 +}
 +
 +QQmlBoundSignal *QQmlBoundSignal::cast(QObject *o)
 +{
 +    QQmlAbstractBoundSignal *s = qobject_cast<QQmlAbstractBoundSignal*>(o);
 +    return static_cast<QQmlBoundSignal *>(s);
 +}
 +
 +int QQmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
 +{
 +    if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
 +        if (!m_expression)
 +            return -1;
-         QQmlProfilerService::endRange(QQmlProfilerService::HandlingSignal);
++
++        if (QQmlDebugService::isDebuggingEnabled())
 +            QV8DebugService::instance()->signalEmitted(QString::fromAscii(m_signal.signature()));
++
++        QQmlHandlingSignalProfiler prof;
++        if (prof.enabled) {
++            prof.setSignalInfo(QString::fromLatin1(m_signal.signature()),
++                               m_expression->expression());
++            prof.setLocation(m_expression->sourceFile(), m_expression->lineNumber(),
++                             m_expression->columnNumber());
 +        }
++
 +        m_isEvaluating = true;
 +        if (!m_paramsValid) {
 +            if (!m_signal.parameterTypes().isEmpty())
 +                m_params = new QQmlBoundSignalParameters(m_signal, this);
 +            m_paramsValid = true;
 +        }
 +
 +        if (m_params) m_params->setValues(a);
 +        if (m_expression && m_expression->engine()) {
 +            QQmlExpressionPrivate::get(m_expression)->value(m_params);
 +            if (m_expression && m_expression->hasError())
 +                QQmlEnginePrivate::warning(m_expression->engine(), m_expression->error());
 +        }
 +        if (m_params) m_params->clearValues();
 +        m_isEvaluating = false;
 +        return -1;
 +    } else {
 +        return QObject::qt_metacall(c, id, a);
 +    }
 +}
 +
 +QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method, 
 +                                                                     QObject *parent)
 +: QObject(parent), types(0), values(0)
 +{
 +    MetaObject *mo = new MetaObject(this);
 +
 +    // ### Optimize!
 +    QMetaObjectBuilder mob;
 +    mob.setSuperClass(&QQmlBoundSignalParameters::staticMetaObject);
 +    mob.setClassName("QQmlBoundSignalParameters");
 +
 +    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 (QQmlMetaType::isQObject(t)) {
 +            types[ii] = QMetaType::QObjectStar;
 +            QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
 +            prop.setWritable(false);
 +        } else {
 +            QByteArray propType = type;
 +            if (t >= QVariant::UserType || t == QVariant::Invalid) {
 +                QByteArray scope;
 +                QByteArray name;
 +                int scopeIdx = propType.lastIndexOf("::");
 +                if (scopeIdx != -1) {
 +                    scope = propType.left(scopeIdx);
 +                    name = propType.mid(scopeIdx + 2);
 +                } else {
 +                    name = propType;
 +                }
 +                const QMetaObject *meta;
 +                if (scope == "Qt")
 +                    meta = &QObject::staticQtMetaObject;
 +                else
 +                    meta = parent->parent()->metaObject();   //### assumes parent->parent()
 +                for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
 +                    QMetaEnum m = meta->enumerator(i);
 +                    if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) {
 +                        t = QVariant::Int;
 +                        propType = "int";
 +                        break;
 +                    }
 +                }
 +            }
 +            types[ii] = t;
 +            QMetaPropertyBuilder prop = mob.addProperty(name, propType);
 +            prop.setWritable(false);
 +        }
 +    }
 +    myMetaObject = mob.toMetaObject();
 +    *static_cast<QMetaObject *>(mo) = *myMetaObject;
 +
 +    d_ptr->metaObject = mo;
 +}
 +
 +QQmlBoundSignalParameters::~QQmlBoundSignalParameters()
 +{
 +    delete [] types;
 +    free(myMetaObject);
 +}
 +
 +void QQmlBoundSignalParameters::setValues(void **v)
 +{
 +    values = v;
 +}
 +
 +void QQmlBoundSignalParameters::clearValues()
 +{
 +    values = 0;
 +}
 +
 +int QQmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
 +{
 +    if (!values)
 +        return -1;
 +
 +    if (c == QMetaObject::ReadProperty && id >= 1) {
 +        int t = types[id - 1];
 +        void *p = a[0];
 +        QMetaType::destruct(t, p);
 +        QMetaType::construct(t, p, values[id]);
 +        return -1;
 +    } else {
 +        return qt_metacall(c, id, a);
 +    }
 +}
 +
 +QT_END_NAMESPACE
 +
 +#include <qqmlboundsignal.moc>
index 65247e1,0000000..23c4adc
mode 100644,000000..100644
--- /dev/null
@@@ -1,3882 -1,0 +1,3904 @@@
-         if (isSharable && !binding.property->isValueTypeSubProperty && !binding.property->isAlias /* See above re alias */ &&
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlcompiler_p.h"
 +
 +#include "qqmlpropertyvaluesource.h"
 +#include "qqmlcomponent.h"
 +#include <private/qmetaobjectbuilder_p.h>
 +#include <private/qfastmetabuilder_p.h>
 +#include "qqmlstringconverters_p.h"
 +#include "qqmlengine_p.h"
 +#include "qqmlengine.h"
 +#include "qqmlcontext.h"
 +#include "qqmlmetatype_p.h"
 +#include "qqmlcustomparser_p_p.h"
 +#include "qqmlcontext_p.h"
 +#include "qqmlcomponent_p.h"
 +#include <private/qqmljsast_p.h>
 +#include "qqmlvmemetaobject_p.h"
 +#include "qqmlexpression_p.h"
 +#include "qqmlproperty_p.h"
 +#include "qqmlrewrite_p.h"
 +#include "qqmlscriptstring.h"
 +#include "qqmlglobal_p.h"
 +#include "qqmlbinding_p.h"
 +#include <private/qv4compiler_p.h>
 +
 +#include <QColor>
 +#include <QDebug>
 +#include <QPointF>
 +#include <QSizeF>
 +#include <QRectF>
 +#include <QAtomicInt>
 +#include <QtCore/qdebug.h>
 +#include <QtCore/qdatetime.h>
 +
 +Q_DECLARE_METATYPE(QList<int>)
 +Q_DECLARE_METATYPE(QList<qreal>)
 +Q_DECLARE_METATYPE(QList<bool>)
 +Q_DECLARE_METATYPE(QList<QString>)
 +Q_DECLARE_METATYPE(QList<QUrl>)
 +
 +QT_BEGIN_NAMESPACE
 +
 +DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
 +DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATS);
 +
 +using namespace QQmlJS;
 +using namespace QQmlScript;
 +using namespace QQmlCompilerTypes;
 +
 +static QString id_string(QLatin1String("id"));
 +static QString on_string(QLatin1String("on"));
 +static QString Changed_string(QLatin1String("Changed"));
 +static QString Component_string(QLatin1String("Component"));
 +static QString Component_import_string(QLatin1String("QML/Component"));
 +static QString qsTr_string(QLatin1String("qsTr"));
 +static QString qsTrId_string(QLatin1String("qsTrId"));
 +
 +/*!
 +    Instantiate a new QQmlCompiler.
 +*/
 +QQmlCompiler::QQmlCompiler(QQmlPool *pool)
 +: pool(pool), output(0), engine(0), unitRoot(0), unit(0), cachedComponentTypeRef(-1),
 +  cachedTranslationContextIndex(-1), componentStats(0)
 +{
 +    if (compilerStatDump()) 
 +        componentStats = pool->New<ComponentStats>();
 +}
 +
 +/*!
 +    Returns true if the last call to compile() caused errors.
 +
 +    \sa errors()
 +*/
 +bool QQmlCompiler::isError() const
 +{
 +    return !exceptions.isEmpty();
 +}
 +
 +/*!
 +    Return the list of errors from the last call to compile(), or an empty list
 +    if there were no errors.
 +*/
 +QList<QQmlError> QQmlCompiler::errors() const
 +{
 +    return exceptions;
 +}
 +
 +/*!
 +    Returns true if \a name refers to an attached property, false otherwise.
 +
 +    Attached property names are those that start with a capital letter.
 +*/
 +bool QQmlCompiler::isAttachedPropertyName(const QString &name)
 +{
 +    return isAttachedPropertyName(QHashedStringRef(&name));
 +}
 +
 +bool QQmlCompiler::isAttachedPropertyName(const QHashedStringRef &name)
 +{
 +    return !name.isEmpty() && name.at(0).isUpper();
 +}
 +
 +/*!
 +    Returns true if \a name refers to a signal property, false otherwise.
 +
 +    Signal property names are those that start with "on", followed by a first
 +    character which is either a capital letter or one or more underscores followed
 +    by a capital letter, which is then followed by other allowed characters.
 +
 +    Note that although ECMA-262r3 supports dollarsigns and escaped unicode
 +    character codes in property names, for simplicity and performance reasons
 +    QML only supports letters, numbers and underscores.
 +*/
 +bool QQmlCompiler::isSignalPropertyName(const QString &name)
 +{
 +    return isSignalPropertyName(QStringRef(&name));
 +}
 +
 +bool QQmlCompiler::isSignalPropertyName(const QHashedStringRef &name)
 +{
 +    if (name.length() < 3) return false;
 +    if (!name.startsWith(on_string)) return false;
 +    int ns = name.length();
 +    for (int i = 2; i < ns; ++i) {
 +        const QChar curr = name.at(i);
 +        if (curr.unicode() == '_') continue;
 +        if (curr.isUpper()) return true;
 +        return false;
 +    }
 +    return false; // consists solely of underscores - invalid.
 +}
 +
 +/*!
 +    \macro COMPILE_EXCEPTION
 +    \internal
 +    Inserts an error into the QQmlCompiler error list, and returns false
 +    (failure).
 +
 +    \a token is used to source the error line and column, and \a desc is the
 +    error itself.  \a desc can be an expression that can be piped into QDebug.
 +
 +    For example:
 +
 +    \code
 +    COMPILE_EXCEPTION(property, tr("Error for property \"%1\"").arg(property->name));
 +    \endcode
 +*/
 +#define COMPILE_EXCEPTION_LOCATION(line, column, desc) \
 +    {  \
 +        QQmlError error; \
 +        error.setUrl(output->url); \
 +        error.setLine(line); \
 +        error.setColumn(column); \
 +        error.setDescription(desc.trimmed()); \
 +        exceptions << error; \
 +        return false; \
 +    }
 +
 +#define COMPILE_EXCEPTION(token, desc) \
 +    COMPILE_EXCEPTION_LOCATION((token)->location.start.line, (token)->location.start.column, desc)
 +
 +/*!
 +    \macro COMPILE_CHECK
 +    \internal
 +    Returns false if \a is false, otherwise does nothing.
 +*/
 +#define COMPILE_CHECK(a) \
 +    { \
 +        if (!a) return false; \
 +    }
 +
 +/*!
 +    Returns true if literal \a v can be assigned to property \a prop, otherwise
 +    false.
 +
 +    This test corresponds to action taken by genLiteralAssignment().  Any change
 +    made here, must have a corresponding action in genLiteralAssigment().
 +*/
 +bool QQmlCompiler::testLiteralAssignment(QQmlScript::Property *prop,
 +                                                 QQmlScript::Value *v)
 +{
 +    const QQmlScript::Variant &value = v->value;
 +
 +    if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration)
 +        COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
 +
 +    if (prop->core.isEnum()) {
 +        QMetaProperty p = prop->parent->metaObject()->property(prop->index);
 +        int enumValue;
 +        bool ok;
 +        if (p.isFlagType()) {
 +            enumValue = p.enumerator().keysToValue(value.asString().toUtf8().constData(), &ok);
 +        } else
 +            enumValue = p.enumerator().keyToValue(value.asString().toUtf8().constData(), &ok);
 +
 +        if (!ok)
 +            COMPILE_EXCEPTION(v, tr("Invalid property assignment: unknown enumeration"));
 +
 +        v->value = QQmlScript::Variant((double)enumValue);
 +        return true;
 +    }
 +
 +    int type = prop->type;
 +
 +    switch(type) {
 +        case QMetaType::QVariant:
 +            break;
 +        case QVariant::String:
 +            if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string expected"));
 +            break;
 +        case QVariant::StringList: // we expect a string literal.  A string list is not a literal assignment.
 +            if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: string or string list expected"));
 +            break;
 +        case QVariant::ByteArray:
 +            if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: byte array expected"));
 +            break;
 +        case QVariant::Url:
 +            if (!v->value.isString()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: url expected"));
 +            break;
 +        case QVariant::RegExp:
 +            COMPILE_EXCEPTION(v, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
 +            break;
 +        case QVariant::UInt:
 +            {
 +            bool ok = v->value.isNumber();
 +            if (ok) {
 +                double n = v->value.asNumber();
 +                if (double(uint(n)) != n)
 +                    ok = false;
 +            }
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsigned int expected"));
 +            }
 +            break;
 +        case QVariant::Int:
 +            {
 +            bool ok = v->value.isNumber();
 +            if (ok) {
 +                double n = v->value.asNumber();
 +                if (double(int(n)) != n)
 +                    ok = false;
 +            }
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: int expected"));
 +            }
 +            break;
 +        case QMetaType::Float:
 +            if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected"));
 +            break;
 +        case QVariant::Double:
 +            if (!v->value.isNumber()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: number expected"));
 +            break;
 +        case QVariant::Color:
 +            {
 +            bool ok;
 +            QQmlStringConverters::colorFromString(value.asString(), &ok);
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: color expected"));
 +            }
 +            break;
 +#ifndef QT_NO_DATESTRING
 +        case QVariant::Date:
 +            {
 +            bool ok;
 +            QQmlStringConverters::dateFromString(value.asString(), &ok);
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: date expected"));
 +            }
 +            break;
 +        case QVariant::Time:
 +            {
 +            bool ok;
 +            QQmlStringConverters::timeFromString(value.asString(), &ok);
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: time expected"));
 +            }
 +            break;
 +        case QVariant::DateTime:
 +            {
 +            bool ok;
 +            QQmlStringConverters::dateTimeFromString(value.asString(), &ok);
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: datetime expected"));
 +            }
 +            break;
 +#endif // QT_NO_DATESTRING
 +        case QVariant::Point:
 +        case QVariant::PointF:
 +            {
 +            bool ok;
 +            QQmlStringConverters::pointFFromString(value.asString(), &ok);
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: point expected"));
 +            }
 +            break;
 +        case QVariant::Size:
 +        case QVariant::SizeF:
 +            {
 +            bool ok;
 +            QQmlStringConverters::sizeFFromString(value.asString(), &ok);
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: size expected"));
 +            }
 +            break;
 +        case QVariant::Rect:
 +        case QVariant::RectF:
 +            {
 +            bool ok;
 +            QQmlStringConverters::rectFFromString(value.asString(), &ok);
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: rect expected"));
 +            }
 +            break;
 +        case QVariant::Bool:
 +            {
 +            if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, tr("Invalid property assignment: boolean expected"));
 +            }
 +            break;
 +        case QVariant::Vector3D:
 +            {
 +            bool ok;
 +            QQmlStringConverters::vector3DFromString(value.asString(), &ok);
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 3D vector expected"));
 +            }
 +            break;
 +        case QVariant::Vector4D:
 +            {
 +            bool ok;
 +            QQmlStringConverters::vector4DFromString(value.asString(), &ok);
 +            if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: 4D vector expected"));
 +            }
 +            break;
 +        default:
 +            {
 +            // check if assigning a literal value to a list property.
 +            // in each case, check the singular, since an Array of the specified type
 +            // will not go via this literal assignment codepath.
 +            if (type == qMetaTypeId<QList<qreal> >()) {
 +                if (!v->value.isNumber()) {
 +                    COMPILE_EXCEPTION(v, tr("Invalid property assignment: real or array of reals expected"));
 +                }
 +                break;
 +            } else if (type == qMetaTypeId<QList<int> >()) {
 +                bool ok = v->value.isNumber();
 +                if (ok) {
 +                    double n = v->value.asNumber();
 +                    if (double(int(n)) != n)
 +                        ok = false;
 +                }
 +                if (!ok) COMPILE_EXCEPTION(v, tr("Invalid property assignment: int or array of ints expected"));
 +                break;
 +            } else if (type == qMetaTypeId<QList<bool> >()) {
 +                if (!v->value.isBoolean()) {
 +                    COMPILE_EXCEPTION(v, tr("Invalid property assignment: bool or array of bools expected"));
 +                }
 +                break;
 +            } else if (type == qMetaTypeId<QList<QString> >()) { // we expect a string literal.  A string list is not a literal assignment.
 +                if (!v->value.isString()) {
 +                    COMPILE_EXCEPTION(v, tr("Invalid property assignment: string or array of strings expected"));
 +                }
 +                break;
 +            } else if (type == qMetaTypeId<QList<QUrl> >()) {
 +                if (!v->value.isString()) {
 +                    COMPILE_EXCEPTION(v, tr("Invalid property assignment: url or array of urls expected"));
 +                }
 +                break;
 +            }
 +
 +            // otherwise, check for existence of string converter to custom type
 +            QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(type);
 +            if (!converter)
 +                COMPILE_EXCEPTION(v, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName((QVariant::Type)type))));
 +            }
 +            break;
 +    }
 +    return true;
 +}
 +
 +static QUrl urlFromUserString(const QString &data)
 +{
 +    QUrl u;
 +    // Preserve any valid percent-encoded octets supplied by the source
 +    u.setEncodedUrl(data.toUtf8(), QUrl::TolerantMode);
 +    return u;
 +}
 +
 +/*!
 +    Generate a store instruction for assigning literal \a v to property \a prop.
 +
 +    Any literal assignment that is approved in testLiteralAssignment() must have
 +    a corresponding action in this method.
 +*/
 +void QQmlCompiler::genLiteralAssignment(QQmlScript::Property *prop,
 +                                                QQmlScript::Value *v)
 +{
 +    if (prop->core.isEnum()) {
 +        Q_ASSERT(v->value.isNumber());
 +        // Preresolved value
 +        int value = (int)v->value.asNumber();
 +
 +        Instruction::StoreInteger instr;
 +        instr.propertyIndex = prop->index;
 +        instr.value = value;
 +        output->addInstruction(instr);
 +        return;
 +    }
 +
 +    int type = prop->type;
 +    switch(type) {
 +        case QMetaType::QVariant:
 +            {
 +            if (v->value.isNumber()) {
 +                double n = v->value.asNumber();
 +                if (double(int(n)) == n) {
 +                    if (prop->core.isVMEProperty()) {
 +                        Instruction::StoreVarInteger instr;
 +                        instr.propertyIndex = prop->index;
 +                        instr.value = int(n);
 +                        output->addInstruction(instr);
 +                    } else {
 +                        Instruction::StoreVariantInteger instr;
 +                        instr.propertyIndex = prop->index;
 +                        instr.value = int(n);
 +                        output->addInstruction(instr);
 +                    }
 +                } else {
 +                    if (prop->core.isVMEProperty()) {
 +                        Instruction::StoreVarDouble instr;
 +                        instr.propertyIndex = prop->index;
 +                        instr.value = n;
 +                        output->addInstruction(instr);
 +                    } else {
 +                        Instruction::StoreVariantDouble instr;
 +                        instr.propertyIndex = prop->index;
 +                        instr.value = n;
 +                        output->addInstruction(instr);
 +                    }
 +                }
 +            } else if (v->value.isBoolean()) {
 +                if (prop->core.isVMEProperty()) {
 +                    Instruction::StoreVarBool instr;
 +                    instr.propertyIndex = prop->index;
 +                    instr.value = v->value.asBoolean();
 +                    output->addInstruction(instr);
 +                } else {
 +                    Instruction::StoreVariantBool instr;
 +                    instr.propertyIndex = prop->index;
 +                    instr.value = v->value.asBoolean();
 +                    output->addInstruction(instr);
 +                }
 +            } else {
 +                if (prop->core.isVMEProperty()) {
 +                    Instruction::StoreVar instr;
 +                    instr.propertyIndex = prop->index;
 +                    instr.value = output->indexForString(v->value.asString());
 +                    output->addInstruction(instr);
 +                } else {
 +                    Instruction::StoreVariant instr;
 +                    instr.propertyIndex = prop->index;
 +                    instr.value = output->indexForString(v->value.asString());
 +                    output->addInstruction(instr);
 +                }
 +            }
 +            }
 +            break;
 +        case QVariant::String:
 +            {
 +            Instruction::StoreString instr;
 +            instr.propertyIndex = prop->index;
 +            instr.value = output->indexForString(v->value.asString());
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::StringList:
 +            {
 +            Instruction::StoreStringList instr;
 +            instr.propertyIndex = prop->index;
 +            instr.value = output->indexForString(v->value.asString());
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::ByteArray:
 +            {
 +            Instruction::StoreByteArray instr;
 +            instr.propertyIndex = prop->index;
 +            instr.value = output->indexForByteArray(v->value.asString().toLatin1());
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::Url:
 +            {
 +            Instruction::StoreUrl instr;
 +            QString string = v->value.asString();
 +            QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(urlFromUserString(string));
 +            instr.propertyIndex = prop->index;
 +            instr.value = output->indexForUrl(u);
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::UInt:
 +            {
 +            Instruction::StoreInteger instr;
 +            instr.propertyIndex = prop->index;
 +            instr.value = uint(v->value.asNumber());
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::Int:
 +            {
 +            Instruction::StoreInteger instr;
 +            instr.propertyIndex = prop->index;
 +            instr.value = int(v->value.asNumber());
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QMetaType::Float:
 +            {
 +            Instruction::StoreFloat instr;
 +            instr.propertyIndex = prop->index;
 +            instr.value = float(v->value.asNumber());
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::Double:
 +            {
 +            Instruction::StoreDouble instr;
 +            instr.propertyIndex = prop->index;
 +            instr.value = v->value.asNumber();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::Color:
 +            {
 +            Instruction::StoreColor instr;
 +            QColor c = QQmlStringConverters::colorFromString(v->value.asString());
 +            instr.propertyIndex = prop->index;
 +            instr.value = c.rgba();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +#ifndef QT_NO_DATESTRING
 +        case QVariant::Date:
 +            {
 +            Instruction::StoreDate instr;
 +            QDate d = QQmlStringConverters::dateFromString(v->value.asString());
 +            instr.propertyIndex = prop->index;
 +            instr.value = d.toJulianDay();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::Time:
 +            {
 +            Instruction::StoreTime instr;
 +            QTime time = QQmlStringConverters::timeFromString(v->value.asString());
 +            instr.propertyIndex = prop->index;
 +            Q_ASSERT(sizeof(instr.time) == sizeof(QTime));
 +            ::memcpy(&instr.time, &time, sizeof(QTime));
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::DateTime:
 +            {
 +            Instruction::StoreDateTime instr;
 +            QDateTime dateTime = QQmlStringConverters::dateTimeFromString(v->value.asString());
 +            QTime time = dateTime.time();
 +            instr.propertyIndex = prop->index;
 +            instr.date = dateTime.date().toJulianDay();
 +            Q_ASSERT(sizeof(instr.time) == sizeof(QTime));
 +            ::memcpy(&instr.time, &time, sizeof(QTime));
 +            output->addInstruction(instr);
 +            }
 +            break;
 +#endif // QT_NO_DATESTRING
 +        case QVariant::Point:
 +            {
 +            Instruction::StorePoint instr;
 +            bool ok;
 +            QPoint point = QQmlStringConverters::pointFFromString(v->value.asString(), &ok).toPoint();
 +            instr.propertyIndex = prop->index;
 +            instr.point.xp = point.x();
 +            instr.point.yp = point.y();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::PointF:
 +            {
 +            Instruction::StorePointF instr;
 +            bool ok;
 +            QPointF point = QQmlStringConverters::pointFFromString(v->value.asString(), &ok);
 +            instr.propertyIndex = prop->index;
 +            instr.point.xp = point.x();
 +            instr.point.yp = point.y();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::Size:
 +            {
 +            Instruction::StoreSize instr;
 +            bool ok;
 +            QSize size = QQmlStringConverters::sizeFFromString(v->value.asString(), &ok).toSize();
 +            instr.propertyIndex = prop->index;
 +            instr.size.wd = size.width();
 +            instr.size.ht = size.height();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::SizeF:
 +            {
 +            Instruction::StoreSizeF instr;
 +            bool ok;
 +            QSizeF size = QQmlStringConverters::sizeFFromString(v->value.asString(), &ok);
 +            instr.propertyIndex = prop->index;
 +            instr.size.wd = size.width();
 +            instr.size.ht = size.height();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::Rect:
 +            {
 +            Instruction::StoreRect instr;
 +            bool ok;
 +            QRect rect = QQmlStringConverters::rectFFromString(v->value.asString(), &ok).toRect();
 +            instr.propertyIndex = prop->index;
 +            instr.rect.x1 = rect.left();
 +            instr.rect.y1 = rect.top();
 +            instr.rect.x2 = rect.right();
 +            instr.rect.y2 = rect.bottom();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::RectF:
 +            {
 +            Instruction::StoreRectF instr;
 +            bool ok;
 +            QRectF rect = QQmlStringConverters::rectFFromString(v->value.asString(), &ok);
 +            instr.propertyIndex = prop->index;
 +            instr.rect.xp = rect.left();
 +            instr.rect.yp = rect.top();
 +            instr.rect.w = rect.width();
 +            instr.rect.h = rect.height();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::Bool:
 +            {
 +            Instruction::StoreBool instr;
 +            bool b = v->value.asBoolean();
 +            instr.propertyIndex = prop->index;
 +            instr.value = b;
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        case QVariant::Vector3D:
 +            {
 +            Instruction::StoreVector3D instr;
 +            bool ok;
 +            QVector3D vector = QQmlStringConverters::vector3DFromString(v->value.asString(), &ok);
 +            instr.propertyIndex = prop->index;
 +            instr.vector.xp = vector.x();
 +            instr.vector.yp = vector.y();
 +            instr.vector.zp = vector.z();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +    case QVariant::Vector4D:
 +            {
 +            Instruction::StoreVector4D instr;
 +            bool ok;
 +            QVector4D vector = QQmlStringConverters::vector4DFromString(v->value.asString(), &ok);
 +            instr.propertyIndex = prop->index;
 +            instr.vector.xp = vector.x();
 +            instr.vector.yp = vector.y();
 +            instr.vector.zp = vector.z();
 +            instr.vector.wp = vector.w();
 +            output->addInstruction(instr);
 +            }
 +            break;
 +        default:
 +            {
 +            // generate single literal value assignment to a list property if required
 +            if (type == qMetaTypeId<QList<qreal> >()) {
 +                Instruction::StoreDoubleQList instr;
 +                instr.propertyIndex = prop->index;
 +                instr.value = v->value.asNumber();
 +                output->addInstruction(instr);
 +                break;
 +            } else if (type == qMetaTypeId<QList<int> >()) {
 +                Instruction::StoreIntegerQList instr;
 +                instr.propertyIndex = prop->index;
 +                instr.value = int(v->value.asNumber());
 +                output->addInstruction(instr);
 +                break;
 +            } else if (type == qMetaTypeId<QList<bool> >()) {
 +                Instruction::StoreBoolQList instr;
 +                bool b = v->value.asBoolean();
 +                instr.propertyIndex = prop->index;
 +                instr.value = b;
 +                output->addInstruction(instr);
 +                break;
 +            } else if (type == qMetaTypeId<QList<QUrl> >()) {
 +                Instruction::StoreUrlQList instr;
 +                QString string = v->value.asString();
 +                QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(urlFromUserString(string));
 +                instr.propertyIndex = prop->index;
 +                instr.value = output->indexForUrl(u);
 +                output->addInstruction(instr);
 +                break;
 +            } else if (type == qMetaTypeId<QList<QString> >()) {
 +                Instruction::StoreStringQList instr;
 +                instr.propertyIndex = prop->index;
 +                instr.value = output->indexForString(v->value.asString());
 +                output->addInstruction(instr);
 +                break;
 +            }
 +
 +            // otherwise, generate custom type literal assignment
 +            Instruction::AssignCustomType instr;
 +            instr.propertyIndex = prop->index;
 +            instr.primitive = output->indexForString(v->value.asString());
 +            instr.type = type;
 +            output->addInstruction(instr);
 +            }
 +            break;
 +    }
 +}
 +
 +/*!
 +    Resets data by clearing the lists that the QQmlCompiler modifies.
 +*/
 +void QQmlCompiler::reset(QQmlCompiledData *data)
 +{
 +    data->types.clear();
 +    data->primitives.clear();
 +    data->datas.clear();
 +    data->bytecode.resize(0);
 +}
 +
 +/*!
 +    Compile \a unit, and store the output in \a out.  \a engine is the QQmlEngine
 +    with which the QQmlCompiledData will be associated.
 +
 +    Returns true on success, false on failure.  On failure, the compile errors
 +    are available from errors().
 +
 +    If the environment variant QML_COMPILER_DUMP is set
 +    (eg. QML_COMPILER_DUMP=1) the compiled instructions will be dumped to stderr
 +    on a successful compiler.
 +*/
 +bool QQmlCompiler::compile(QQmlEngine *engine,
 +                                   QQmlTypeData *unit,
 +                                   QQmlCompiledData *out)
 +{
 +    exceptions.clear();
 +
 +    Q_ASSERT(out);
 +    reset(out);
 +
 +    QQmlScript::Object *root = unit->parser().tree();
 +    Q_ASSERT(root);
 +
 +    this->engine = engine;
 +    this->enginePrivate = QQmlEnginePrivate::get(engine);
 +    this->unit = unit;
 +    this->unitRoot = root;
 +    this->output = out;
 +
 +    // Compile types
 +    const QList<QQmlTypeData::TypeReference>  &resolvedTypes = unit->resolvedTypes();
 +    QList<QQmlScript::TypeReference *> referencedTypes = unit->parser().referencedTypes();
 +
 +    for (int ii = 0; ii < resolvedTypes.count(); ++ii) {
 +        QQmlCompiledData::TypeReference ref;
 +
 +        const QQmlTypeData::TypeReference &tref = resolvedTypes.at(ii);
 +        QQmlScript::TypeReference *parserRef = referencedTypes.at(ii);
 +
 +        if (tref.type) {
 +            ref.type = tref.type;
 +            if (!ref.type->isCreatable()) {
 +                QString err = ref.type->noCreationReason();
 +                if (err.isEmpty())
 +                    err = tr( "Element is not creatable.");
 +                COMPILE_EXCEPTION(parserRef->refObjects.first(), err);
 +            }
 +            
 +            if (ref.type->containsRevisionedAttributes()) {
 +                QQmlError cacheError;
 +                ref.typePropertyCache = enginePrivate->cache(ref.type, resolvedTypes.at(ii).minorVersion, 
 +                                                             cacheError);
 +                if (!ref.typePropertyCache) 
 +                    COMPILE_EXCEPTION(parserRef->refObjects.first(), cacheError.description());
 +                ref.typePropertyCache->addref();
 +            }
 +
 +        } else if (tref.typeData) {
 +            ref.component = tref.typeData->compiledData();
 +        }
 +        ref.className = parserRef->name;
 +        out->types << ref;
 +    }
 +
 +    compileTree(root);
 +
 +    if (!isError()) {
 +        if (compilerDump())
 +            out->dumpInstructions();
 +        if (componentStats)
 +            dumpStats();
 +        Q_ASSERT(out->rootPropertyCache);
 +    } else {
 +        reset(out);
 +    }
 +
 +    compileState = 0;
 +    output = 0;
 +    this->engine = 0;
 +    this->enginePrivate = 0;
 +    this->unit = 0;
 +    this->cachedComponentTypeRef = -1;
 +    this->cachedTranslationContextIndex = -1;
 +    this->unitRoot = 0;
 +
 +    return !isError();
 +}
 +
 +void QQmlCompiler::compileTree(QQmlScript::Object *tree)
 +{
 +    compileState = pool->New<ComponentCompileState>();
 +
 +    compileState->root = tree;
 +    if (componentStats)
 +        componentStats->componentStat.lineNumber = tree->location.start.line;
 +
 +    // We generate the importCache before we build the tree so that
 +    // it can be used in the binding compiler.  Given we "expect" the
 +    // QML compilation to succeed, this isn't a waste.
 +    output->importCache = new QQmlTypeNameCache();
 +    foreach (const QString &ns, unit->namespaces()) {
 +        output->importCache->add(ns);
 +    }
 +
 +    int scriptIndex = 0;
 +    foreach (const QQmlTypeData::ScriptReference &script, unit->resolvedScripts()) {
 +        QString qualifier = script.qualifier;
 +        QString enclosingNamespace;
 +
 +        const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
 +        if (lastDotIndex != -1) {
 +            enclosingNamespace = qualifier.left(lastDotIndex);
 +            qualifier = qualifier.mid(lastDotIndex+1);
 +        }
 +
 +        output->importCache->add(qualifier, scriptIndex++, enclosingNamespace);
 +    }
 +
 +    unit->imports().populateCache(output->importCache, engine);
 +
 +    if (!buildObject(tree, BindingContext()) || !completeComponentBuild())
 +        return;
 +
 +    Instruction::Init init;
 +    init.bindingsSize = compileState->totalBindingsCount;
 +    init.parserStatusSize = compileState->parserStatusCount;
 +    init.contextCache = genContextCache();
 +    init.objectStackSize = compileState->objectDepth.maxDepth();
 +    init.listStackSize = compileState->listDepth.maxDepth();
 +    if (compileState->compiledBindingData.isEmpty())
 +        init.compiledBinding = -1;
 +    else
 +        init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData);
 +    output->addInstruction(init);
 +
 +    foreach (const QQmlTypeData::ScriptReference &script, unit->resolvedScripts()) {
 +        Instruction::StoreImportedScript import;
 +        import.value = output->scripts.count();
 +
 +        QQmlScriptData *scriptData = script.script->scriptData();
 +        scriptData->addref();
 +        output->scripts << scriptData;
 +        output->addInstruction(import);
 +    }
 +
 +    if (!compileState->v8BindingProgram.isEmpty()) {
 +        Instruction::InitV8Bindings bindings;
 +        int index = output->programs.count();
 +
 +        typedef QQmlCompiledData::V8Program V8Program;
 +        output->programs.append(V8Program(compileState->v8BindingProgram, output));
 +
 +        bindings.programIndex = index;
 +        bindings.line = compileState->v8BindingProgramLine;
 +        output->addInstruction(bindings);
 +    }
 +
 +    genObject(tree);
 +
 +    Instruction::SetDefault def;
 +    output->addInstruction(def);
 +
 +    Instruction::Done done;
 +    output->addInstruction(done);
 +
 +    Q_ASSERT(tree->metatype);
 +
 +    if (tree->metadata.isEmpty()) {
 +        output->root = tree->metatype;
 +    } else {
 +        static_cast<QMetaObject &>(output->rootData) = *tree->metaObject();
 +        output->root = &output->rootData;
 +    }
 +    if (!tree->metadata.isEmpty()) 
 +        enginePrivate->registerCompositeType(output);
 +}
 +
 +static bool QStringList_contains(const QStringList &list, const QHashedStringRef &string)
 +{
 +    for (int ii = 0; ii < list.count(); ++ii)
 +        if (string == list.at(ii))
 +            return true;
 +
 +    return false;
 +}
 +
 +bool QQmlCompiler::buildObject(QQmlScript::Object *obj, const BindingContext &ctxt)
 +{
 +    if (componentStats)
 +        componentStats->componentStat.objects++;
 +
 +    Q_ASSERT (obj->type != -1);
 +    const QQmlCompiledData::TypeReference &tr = output->types.at(obj->type);
 +    obj->metatype = tr.metaObject();
 +
 +    if (tr.type) 
 +        obj->typeName = tr.type->qmlTypeName();
 +
 +    // This object is a "Component" element
 +    if (tr.type && obj->metatype == &QQmlComponent::staticMetaObject) {
 +        COMPILE_CHECK(buildComponent(obj, ctxt));
 +        return true;
 +    } 
 +
 +    if (tr.component) {
 +        typedef QQmlInstruction I; 
 +        const I *init = ((const I *)tr.component->bytecode.constData());
 +        Q_ASSERT(init && tr.component->instructionType(init) == QQmlInstruction::Init);
 + 
 +        // Adjust stack depths to include nested components
 +        compileState->objectDepth.pushPop(init->init.objectStackSize);
 +        compileState->listDepth.pushPop(init->init.listStackSize);
 +        compileState->parserStatusCount += init->init.parserStatusSize;
 +        compileState->totalBindingsCount += init->init.bindingsSize;
 +    }
 +
 +    compileState->objectDepth.push();
 +
 +    // Object instantiations reset the binding context
 +    BindingContext objCtxt(obj);
 +
 +    // Create the synthesized meta object, ignoring aliases
 +    COMPILE_CHECK(checkDynamicMeta(obj)); 
 +    COMPILE_CHECK(mergeDynamicMetaProperties(obj));
 +    COMPILE_CHECK(buildDynamicMeta(obj, IgnoreAliases));
 +
 +    // Find the native type and check for the QQmlParserStatus interface
 +    QQmlType *type = toQmlType(obj);
 +    Q_ASSERT(type);
 +    obj->parserStatusCast = type->parserStatusCast();
 +    if (obj->parserStatusCast != -1)
 +        compileState->parserStatusCount++;
 +
 +    // Check if this is a custom parser type.  Custom parser types allow
 +    // assignments to non-existent properties.  These assignments are then
 +    // compiled by the type.
 +    bool isCustomParser = output->types.at(obj->type).type &&
 +                          output->types.at(obj->type).type->customParser() != 0;
 +    QList<QQmlCustomParserProperty> customProps;
 +
 +    // Fetch the list of deferred properties
 +    QStringList deferredList = deferredProperties(obj);
 +
 +    // Must do id property first.  This is to ensure that the id given to any
 +    // id reference created matches the order in which the objects are
 +    // instantiated
 +    for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
 +        if (prop->name() == id_string) {
 +            COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
 +            break;
 +        }
 +    }
 +
 +    // Merge 
 +    Property *defaultProperty = 0;
 +    Property *skipProperty = 0;
 +    if (obj->defaultProperty) {
 +        defaultProperty = obj->defaultProperty;
 +
 +        Property *explicitProperty = 0;
 +
 +        const QMetaObject *mo = obj->metatype;
 +        int idx = mo->indexOfClassInfo("DefaultProperty"); 
 +        if (idx != -1) {
 +            QMetaClassInfo info = mo->classInfo(idx);
 +            const char *p = info.value();
 +            if (p) {
 +                int plen = 0;
 +                char ord = 0;
 +                while (char c = p[plen++]) { ord |= c; };
 +                --plen;
 +
 +                if (ord & 0x80) {
 +                    // Utf8 - unoptimal, but seldom hit
 +                    QString *s = pool->NewString(QString::fromUtf8(p, plen));
 +                    QHashedStringRef r(*s);
 +
 +                    if (obj->propertiesHashField.test(r.hash())) {
 +                        for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
 +                            if (ep->name() == r) {
 +                                explicitProperty = ep;
 +                                break;
 +                            }
 +                        }
 +                    }
 +
 +                    if (!explicitProperty)
 +                        defaultProperty->setName(r);
 +
 +                } else {
 +                    QHashedCStringRef r(p, plen); 
 +
 +                    if (obj->propertiesHashField.test(r.hash())) {
 +                        for (Property *ep = obj->properties.first(); ep; ep = obj->properties.next(ep)) {
 +                            if (ep->name() == r) {
 +                                explicitProperty = ep;
 +                                break;
 +                            }
 +                        }
 +                    }
 +
 +                    if (!explicitProperty) {
 +                        // Set the default property name
 +                        QChar *buffer = pool->NewRawArray<QChar>(r.length());
 +                        r.writeUtf16(buffer);
 +                        defaultProperty->setName(QHashedStringRef(buffer, r.length(), r.hash()));
 +                    }
 +                }
 +            }
 +        }
 +
 +        if (explicitProperty && !explicitProperty->value && !explicitProperty->values.isEmpty()) {
 +
 +            skipProperty = explicitProperty; // We merge the values into defaultProperty
 +
 +            // Find the correct insertion point
 +            Value *insertPos = 0;
 +
 +            for (Value *v = defaultProperty->values.first(); v; v = Property::ValueList::next(v)) {
 +                if (!(v->location.start < explicitProperty->values.first()->location.start))
 +                    break;
 +                insertPos = v;
 +            }
 +
 +            defaultProperty->values.insertAfter(insertPos, explicitProperty->values);
 +        } 
 +    }
 +
 +    QQmlCustomParser *cp = 0;
 +    if (isCustomParser)
 +        cp = output->types.at(obj->type).type->customParser();
 +
 +    // Build all explicit properties specified
 +    for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
 +
 +        if (prop == skipProperty)
 +            continue;
 +        if (prop->name() == id_string)
 +            continue;
 +
 +        bool canDefer = false;
 +        if (isCustomParser) {
 +            if (doesPropertyExist(prop, obj) &&
 +                (!(cp->flags() & QQmlCustomParser::AcceptsAttachedProperties) ||
 +                 !isAttachedPropertyName(prop->name()))) {
 +                int ids = compileState->ids.count();
 +                COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
 +                canDefer = ids == compileState->ids.count();
 +            } else if (isSignalPropertyName(prop->name()) &&
 +                    (cp->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
 +                COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
 +            } else {
 +                customProps << QQmlCustomParserNodePrivate::fromProperty(prop);
 +            }
 +        } else {
 +            if (isSignalPropertyName(prop->name())) {
 +                COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
 +            } else {
 +                int ids = compileState->ids.count();
 +                COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
 +                canDefer = ids == compileState->ids.count();
 +            }
 +        }
 +
 +        if (canDefer && !deferredList.isEmpty() && QStringList_contains(deferredList, prop->name()))
 +            prop->isDeferred = true;
 +
 +    }
 +
 +    // Build the default property
 +    if (defaultProperty)  {
 +        Property *prop = defaultProperty;
 +
 +        bool canDefer = false;
 +        if (isCustomParser) {
 +            if (doesPropertyExist(prop, obj)) {
 +                int ids = compileState->ids.count();
 +                COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
 +                canDefer = ids == compileState->ids.count();
 +            } else {
 +                customProps << QQmlCustomParserNodePrivate::fromProperty(prop);
 +            }
 +        } else {
 +            int ids = compileState->ids.count();
 +            COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
 +            canDefer = ids == compileState->ids.count();
 +        }
 +
 +        if (canDefer && !deferredList.isEmpty() && QStringList_contains(deferredList, prop->name()))
 +            prop->isDeferred = true;
 +    }
 +
 +    // Compile custom parser parts
 +    if (isCustomParser && !customProps.isEmpty()) {
 +        cp->clearErrors();
 +        cp->compiler = this;
 +        cp->object = obj;
 +        obj->custom = cp->compile(customProps);
 +        cp->compiler = 0;
 +        cp->object = 0;
 +        foreach (QQmlError err, cp->errors()) {
 +            err.setUrl(output->url);
 +            exceptions << err;
 +        }
 +    }
 +
 +    compileState->objectDepth.pop();
 +
 +    return true;
 +}
 +
 +void QQmlCompiler::genObject(QQmlScript::Object *obj)
 +{
 +    QQmlCompiledData::TypeReference &tr = output->types[obj->type];
 +    if (tr.type && obj->metatype == &QQmlComponent::staticMetaObject) {
 +        genComponent(obj);
 +        return;
 +    }
 +
 +    // Create the object
 +    if (obj->custom.isEmpty() && output->types.at(obj->type).type &&
 +        !output->types.at(obj->type).type->isExtendedType() && obj != compileState->root) {
 +
 +        Instruction::CreateSimpleObject create;
 +        create.create = output->types.at(obj->type).type->createFunction();
 +        create.typeSize = output->types.at(obj->type).type->createSize();
 +        create.type = obj->type;
 +        create.line = obj->location.start.line;
 +        create.column = obj->location.start.column;
 +        output->addInstruction(create);
 +
 +    } else {
 +
 +        if (output->types.at(obj->type).type) {
 +            Instruction::CreateCppObject create;
 +            create.line = obj->location.start.line;
 +            create.column = obj->location.start.column;
 +            create.data = -1;
 +            if (!obj->custom.isEmpty())
 +                create.data = output->indexForByteArray(obj->custom);
 +            create.type = obj->type;
 +            create.isRoot = (compileState->root == obj);
 +            output->addInstruction(create);
 +        } else {
 +            Instruction::CreateQMLObject create;
 +            create.type = obj->type;
 +            create.isRoot = (compileState->root == obj);
 +
 +            if (!obj->bindingBitmask.isEmpty()) {
 +                Q_ASSERT(obj->bindingBitmask.size() % 4 == 0);
 +                create.bindingBits = output->indexForByteArray(obj->bindingBitmask);
 +            } else {
 +                create.bindingBits = -1;
 +            }
 +            output->addInstruction(create);
 +
 +            Instruction::CompleteQMLObject complete;
 +            complete.line = obj->location.start.line;
 +            complete.column = obj->location.start.column;
 +            complete.isRoot = (compileState->root == obj);
 +            output->addInstruction(complete);
 +        }
 +    }
 +
 +    // Setup the synthesized meta object if necessary
 +    if (!obj->metadata.isEmpty()) {
 +        Instruction::StoreMetaObject meta;
 +        meta.data = output->indexForByteArray(obj->metadata);
 +        meta.aliasData = output->indexForByteArray(obj->synthdata);
 +        meta.propertyCache = output->propertyCaches.count();
 +
 +        QQmlPropertyCache *propertyCache = obj->synthCache;
 +        Q_ASSERT(propertyCache);
 +        propertyCache->addref();
 +
 +        // Add flag for alias properties
 +        if (!obj->synthdata.isEmpty()) {
 +            const QQmlVMEMetaData *vmeMetaData = 
 +                reinterpret_cast<const QQmlVMEMetaData *>(obj->synthdata.constData());
 +            for (int ii = 0; ii < vmeMetaData->aliasCount; ++ii) {
 +                int index = obj->metaObject()->propertyOffset() + vmeMetaData->propertyCount + ii;
 +                QQmlPropertyData *data = propertyCache->property(index);
 +                data->setFlags(data->getFlags() | QQmlPropertyData::IsAlias);
 +            }
 +        }
 +
 +        if (obj == unitRoot) {
 +            propertyCache->addref();
 +            output->rootPropertyCache = propertyCache;
 +        }
 +
 +        output->propertyCaches << propertyCache;
 +        output->addInstruction(meta);
 +    } else if (obj == unitRoot) {
 +        output->rootPropertyCache = tr.createPropertyCache(engine);
 +        output->rootPropertyCache->addref();
 +    }
 +
 +    // Set the object id
 +    if (!obj->id.isEmpty()) {
 +        Instruction::SetId id;
 +        id.value = output->indexForString(obj->id);
 +        id.index = obj->idIndex;
 +        output->addInstruction(id);
 +    }
 +
 +    // Begin the class
 +    if (tr.type && obj->parserStatusCast != -1) {
 +        Instruction::BeginObject begin;
 +        begin.castValue = obj->parserStatusCast;
 +        output->addInstruction(begin);
 +    }
 +
 +    genObjectBody(obj);
 +}
 +
 +void QQmlCompiler::genObjectBody(QQmlScript::Object *obj)
 +{
 +    for (Property *prop = obj->scriptStringProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
 +        Q_ASSERT(prop->scriptStringScope != -1);
 +        const QString &script = prop->values.first()->value.asScript();
 +        Instruction::StoreScriptString ss;
 +        ss.propertyIndex = prop->index;
 +        ss.value = output->indexForString(script);
 +        ss.scope = prop->scriptStringScope;
 +//        ss.bindingId = rewriteBinding(script, prop->name());
 +        ss.bindingId = rewriteBinding(prop->values.first()->value, QString()); // XXX
 +        ss.line = prop->location.start.line;
 +        ss.column = prop->location.start.column;
 +        output->addInstruction(ss);
 +    }
 +
 +    bool seenDefer = false;
 +    for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
 +        if (prop->isDeferred) {
 +            seenDefer = true;
 +            continue;
 +        }
 +        if (!prop->isAlias)
 +            genValueProperty(prop, obj);
 +    }
 +    if (seenDefer) {
 +        Instruction::Defer defer;
 +        defer.deferCount = 0;
 +        int deferIdx = output->addInstruction(defer);
 +        int nextInstructionIndex = output->nextInstructionIndex();
 +
 +        Instruction::DeferInit dinit;
 +        // XXX - these are now massive over allocations
 +        dinit.bindingsSize = compileState->totalBindingsCount;
 +        dinit.parserStatusSize = compileState->parserStatusCount; 
 +        dinit.objectStackSize = compileState->objectDepth.maxDepth(); 
 +        dinit.listStackSize = compileState->listDepth.maxDepth(); 
 +        output->addInstruction(dinit);
 +
 +        for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
 +            if (!prop->isDeferred)
 +                continue;
 +            genValueProperty(prop, obj);
 +        }
 +
 +        Instruction::Done done;
 +        output->addInstruction(done);
 +
 +        output->instruction(deferIdx)->defer.deferCount = output->nextInstructionIndex() - nextInstructionIndex;
 +    }
 +
 +    for (Property *prop = obj->signalProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
 +
 +        QQmlScript::Value *v = prop->values.first();
 +
 +        if (v->type == Value::SignalObject) {
 +
 +            genObject(v->object);
 +
 +            Instruction::AssignSignalObject assign;
 +            assign.line = v->location.start.line;
 +            assign.signal = output->indexForString(prop->name().toString());
 +            output->addInstruction(assign);
 +
 +        } else if (v->type == Value::SignalExpression) {
 +
 +            Instruction::StoreSignal store;
 +            store.signalIndex = prop->index;
 +            const QString &rewrite = rewriteSignalHandler(v->value, prop->name().toString());
 +            store.value = output->indexForByteArray(rewrite.toUtf8());
 +            store.context = v->signalExpressionContextStack;
 +            store.line = v->location.start.line;
 +            store.column = v->location.start.column;
 +            output->addInstruction(store);
 +
 +        }
 +
 +    }
 +
 +    for (Property *prop = obj->attachedProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
 +        Instruction::FetchAttached fetch;
 +        fetch.id = prop->index;
 +        fetch.line = prop->location.start.line;
 +        output->addInstruction(fetch);
 +
 +        genObjectBody(prop->value);
 +
 +        Instruction::PopFetchedObject pop;
 +        output->addInstruction(pop);
 +    }
 +
 +    for (Property *prop = obj->groupedProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
 +        Instruction::FetchObject fetch;
 +        fetch.property = prop->index;
 +        fetch.line = prop->location.start.line;
 +        output->addInstruction(fetch);
 +
 +        if (!prop->value->metadata.isEmpty()) {
 +            Instruction::StoreMetaObject meta;
 +            meta.data = output->indexForByteArray(prop->value->metadata);
 +            meta.aliasData = output->indexForByteArray(prop->value->synthdata);
 +            meta.propertyCache = -1;
 +            output->addInstruction(meta);
 +        }
 +
 +        genObjectBody(prop->value);
 +
 +        Instruction::PopFetchedObject pop;
 +        output->addInstruction(pop);
 +    }
 +
 +    for (Property *prop = obj->valueTypeProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
 +        if (!prop->isAlias)
 +            genValueTypeProperty(obj, prop);
 +    }
 +
 +    for (Property *prop = obj->valueProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
 +        if (prop->isDeferred) 
 +            continue;
 +        if (prop->isAlias)
 +            genValueProperty(prop, obj);
 +    }
 +
 +    for (Property *prop = obj->valueTypeProperties.first(); prop; prop = Object::PropertyList::next(prop)) {
 +        if (prop->isAlias)
 +            genValueTypeProperty(obj, prop);
 +    }
 +}
 +
 +void QQmlCompiler::genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *prop)
 +{
 +    Instruction::FetchValueType fetch;
 +    fetch.property = prop->index;
 +    fetch.type = prop->type;
 +    fetch.bindingSkipList = 0;
 +
 +    if (obj->type == -1 || output->types.at(obj->type).component) {
 +        // We only have to do this if this is a composite type.  If it is a builtin
 +        // type it can't possibly already have bindings that need to be cleared.
 +        for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) {
 +            if (!vprop->values.isEmpty()) {
 +                Q_ASSERT(vprop->index >= 0 && vprop->index < 32);
 +                fetch.bindingSkipList |= (1 << vprop->index);
 +            }
 +        }
 +    }
 +
 +    output->addInstruction(fetch);
 +
 +    for (Property *vprop = prop->value->valueProperties.first(); vprop; vprop = Object::PropertyList::next(vprop)) {
 +        genPropertyAssignment(vprop, prop->value, prop);
 +    }
 +
 +    Instruction::PopValueType pop;
 +    pop.property = prop->index;
 +    pop.type = prop->type;
 +    pop.bindingSkipList = 0;
 +    output->addInstruction(pop);
 +}
 +
 +void QQmlCompiler::genComponent(QQmlScript::Object *obj)
 +{
 +    QQmlScript::Object *root = obj->defaultProperty->values.first()->object;
 +    Q_ASSERT(root);
 +
 +    Instruction::CreateComponent create;
 +    create.line = root->location.start.line;
 +    create.column = root->location.start.column;
 +    create.endLine = root->location.end.line;
 +    create.isRoot = (compileState->root == obj);
 +    int createInstruction = output->addInstruction(create);
 +    int nextInstructionIndex = output->nextInstructionIndex();
 +
 +    ComponentCompileState *oldCompileState = compileState;
 +    compileState = componentState(root);
 +
 +    Instruction::Init init;
 +    init.bindingsSize = compileState->totalBindingsCount;
 +    init.parserStatusSize = compileState->parserStatusCount;
 +    init.contextCache = genContextCache();
 +    init.objectStackSize = compileState->objectDepth.maxDepth();
 +    init.listStackSize = compileState->listDepth.maxDepth();
 +    if (compileState->compiledBindingData.isEmpty())
 +        init.compiledBinding = -1;
 +    else
 +        init.compiledBinding = output->indexForByteArray(compileState->compiledBindingData);
 +    output->addInstruction(init);
 +
 +    if (!compileState->v8BindingProgram.isEmpty()) {
 +        Instruction::InitV8Bindings bindings;
 +        int index = output->programs.count();
 +
 +        typedef QQmlCompiledData::V8Program V8Program;
 +        output->programs.append(V8Program(compileState->v8BindingProgram, output));
 +
 +        bindings.programIndex = index;
 +        bindings.line = compileState->v8BindingProgramLine;
 +        output->addInstruction(bindings);
 +    }
 +
 +    genObject(root);
 +
 +    Instruction::SetDefault def;
 +    output->addInstruction(def);
 +
 +    Instruction::Done done;
 +    output->addInstruction(done);
 +
 +    output->instruction(createInstruction)->createComponent.count = 
 +        output->nextInstructionIndex() - nextInstructionIndex;
 +
 +    compileState = oldCompileState;
 +
 +    if (!obj->id.isEmpty()) {
 +        Instruction::SetId id;
 +        id.value = output->indexForString(obj->id);
 +        id.index = obj->idIndex;
 +        output->addInstruction(id);
 +    }
 +
 +    if (obj == unitRoot) {
 +        output->rootPropertyCache = output->types[obj->type].createPropertyCache(engine);
 +        output->rootPropertyCache->addref();
 +    }
 +}
 +
 +bool QQmlCompiler::buildComponent(QQmlScript::Object *obj,
 +                                 const BindingContext &ctxt)
 +{
 +    // The special "Component" element can only have the id property and a
 +    // default property, that actually defines the component's tree
 +
 +    compileState->objectDepth.push();
 +
 +    // Find, check and set the "id" property (if any)
 +    Property *idProp = 0;
 +    if (obj->properties.isMany() ||
 +       (obj->properties.isOne() && obj->properties.first()->name() != id_string))
 +        COMPILE_EXCEPTION(obj->properties.first(), tr("Component elements may not contain properties other than id"));
 +       
 +    if (!obj->properties.isEmpty())
 +        idProp = obj->properties.first();
 +
 +    if (idProp) {
 +       if (idProp->value || idProp->values.isMany() || idProp->values.first()->object) 
 +           COMPILE_EXCEPTION(idProp, tr("Invalid component id specification"));
 +       COMPILE_CHECK(checkValidId(idProp->values.first(), idProp->values.first()->primitive()))
 +
 +        QString idVal = idProp->values.first()->primitive();
 +
 +        if (compileState->ids.value(idVal))
 +            COMPILE_EXCEPTION(idProp, tr("id is not unique"));
 +
 +        obj->id = idVal;
 +        addId(idVal, obj);
 +    }
 +
 +    // Check the Component tree is well formed
 +    if (obj->defaultProperty &&
 +       (obj->defaultProperty->value || obj->defaultProperty->values.isMany() ||
 +        (obj->defaultProperty->values.isOne() && !obj->defaultProperty->values.first()->object)))
 +        COMPILE_EXCEPTION(obj, tr("Invalid component body specification"));
 +
 +    if (!obj->dynamicProperties.isEmpty())
 +        COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new properties."));
 +    if (!obj->dynamicSignals.isEmpty())
 +        COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new signals."));
 +    if (!obj->dynamicSlots.isEmpty())
 +        COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
 +
 +    QQmlScript::Object *root = 0;
 +    if (obj->defaultProperty && !obj->defaultProperty->values.isEmpty())
 +        root = obj->defaultProperty->values.first()->object;
 +
 +    if (!root)
 +        COMPILE_EXCEPTION(obj, tr("Cannot create empty component specification"));
 +
 +    // Build the component tree
 +    COMPILE_CHECK(buildComponentFromRoot(root, ctxt));
 +
 +    compileState->objectDepth.pop();
 +
 +    return true;
 +}
 +
 +bool QQmlCompiler::buildComponentFromRoot(QQmlScript::Object *obj,
 +                                         const BindingContext &ctxt)
 +{
 +    ComponentCompileState *oldComponentCompileState = compileState;
 +    compileState = pool->New<ComponentCompileState>();
 +    compileState->root = obj;
 +    compileState->nested = true;
 +
 +    if (componentStats) {
 +        ComponentStat oldComponentStat = componentStats->componentStat;
 +
 +        componentStats->componentStat = ComponentStat();
 +        componentStats->componentStat.lineNumber = obj->location.start.line;
 +
 +        if (obj)
 +            COMPILE_CHECK(buildObject(obj, ctxt));
 +
 +        COMPILE_CHECK(completeComponentBuild());
 +
 +        componentStats->componentStat = oldComponentStat;
 +    } else {
 +        if (obj)
 +            COMPILE_CHECK(buildObject(obj, ctxt));
 +
 +        COMPILE_CHECK(completeComponentBuild());
 +    }
 +
 +    compileState = oldComponentCompileState;
 +
 +    return true;
 +}
 +
 +
 +// Build a sub-object.  A sub-object is one that was not created directly by
 +// QML - such as a grouped property object, or an attached object.  Sub-object's
 +// can't have an id, involve a custom parser, have attached properties etc.
 +bool QQmlCompiler::buildSubObject(QQmlScript::Object *obj, const BindingContext &ctxt)
 +{
 +    Q_ASSERT(obj->metatype);
 +    Q_ASSERT(!obj->defaultProperty);
 +    Q_ASSERT(ctxt.isSubContext()); // sub-objects must always be in a binding
 +                                   // sub-context
 +
 +    for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
 +        if (isSignalPropertyName(prop->name())) {
 +            COMPILE_CHECK(buildSignal(prop, obj, ctxt));
 +        } else {
 +            COMPILE_CHECK(buildProperty(prop, obj, ctxt));
 +        }
 +    }
 +
 +    return true;
 +}
 +
 +int QQmlCompiler::componentTypeRef()
 +{
 +    if (cachedComponentTypeRef == -1) {
 +        QQmlType *t = QQmlMetaType::qmlType(Component_import_string,1,0);
 +        for (int ii = output->types.count() - 1; ii >= 0; --ii) {
 +            if (output->types.at(ii).type == t) {
 +                cachedComponentTypeRef = ii;
 +                return ii;
 +            }
 +        }
 +        QQmlCompiledData::TypeReference ref;
 +        ref.className = Component_string;
 +        ref.type = t;
 +        output->types << ref;
 +        cachedComponentTypeRef = output->types.count() - 1;
 +    }
 +    return cachedComponentTypeRef;
 +}
 +
 +int QQmlCompiler::translationContextIndex()
 +{
 +    if (cachedTranslationContextIndex == -1) {
 +        // This code must match that in the qsTr() implementation
 +        const QString &path = output->name;
 +        int lastSlash = path.lastIndexOf(QLatin1Char('/'));
 +        QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) :
 +                                             QString();
 +        QByteArray contextUtf8 = context.toUtf8();
 +        cachedTranslationContextIndex = output->indexForByteArray(contextUtf8);
 +    }
 +    return cachedTranslationContextIndex;
 +}
 +
 +bool QQmlCompiler::buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
 +                                       const BindingContext &ctxt)
 +{
 +    Q_ASSERT(obj->metaObject());
 +
 +    const QHashedStringRef &propName = prop->name();
 +
 +    Q_ASSERT(propName.startsWith(on_string));
 +    QString name = propName.mid(2, -1).toString();
 +
 +    // Note that the property name could start with any alpha or '_' or '$' character,
 +    // so we need to do the lower-casing of the first alpha character.
 +    for (int firstAlphaIndex = 0; firstAlphaIndex < name.size(); ++firstAlphaIndex) {
 +        if (name.at(firstAlphaIndex).isUpper()) {
 +            name[firstAlphaIndex] = name.at(firstAlphaIndex).toLower();
 +            break;
 +        }
 +    }
 +
 +    bool notInRevision = false;
 +
 +    QQmlPropertyData *sig = signal(obj, QStringRef(&name), &notInRevision);
 +
 +    if (sig == 0) {
 +
 +        if (notInRevision && 0 == property(obj, propName, 0)) {
 +            Q_ASSERT(obj->type != -1);
 +            const QList<QQmlTypeData::TypeReference>  &resolvedTypes = unit->resolvedTypes();
 +            const QQmlTypeData::TypeReference &type = resolvedTypes.at(obj->type);
 +            if (type.type) {
 +                COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion));
 +            } else {
 +                COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString()));
 +            }
 +        }
 +
 +        // If the "on<Signal>" name doesn't resolve into a signal, try it as a
 +        // property.
 +        COMPILE_CHECK(buildProperty(prop, obj, ctxt));
 +
 +    }  else {
 +
 +        if (prop->value || !prop->values.isOne())
 +            COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal assignment"));
 +
 +        prop->index = sig->coreIndex;
 +        prop->core = *sig;
 +
 +        obj->addSignalProperty(prop);
 +
 +        if (prop->values.first()->object) {
 +            COMPILE_CHECK(buildObject(prop->values.first()->object, ctxt));
 +            prop->values.first()->type = Value::SignalObject;
 +        } else {
 +            prop->values.first()->type = Value::SignalExpression;
 +
 +            if (!prop->values.first()->value.isScript())
 +                COMPILE_EXCEPTION(prop, tr("Cannot assign a value to a signal (expecting a script to be run)"));
 +
 +            QString script = prop->values.first()->value.asScript().trimmed();
 +            if (script.isEmpty())
 +                COMPILE_EXCEPTION(prop, tr("Empty signal assignment"));
 +
 +            prop->values.first()->signalExpressionContextStack = ctxt.stack;
 +        }
 +    }
 +
 +    return true;
 +}
 +
 +
 +/*!
 +    Returns true if (value) property \a prop exists on obj, false otherwise.
 +*/
 +bool QQmlCompiler::doesPropertyExist(QQmlScript::Property *prop,
 +                                             QQmlScript::Object *obj)
 +{
 +    if (prop->name().isEmpty())
 +        return false;
 +    if(isAttachedPropertyName(prop->name()) || prop->name() == id_string)
 +        return true;
 +
 +    return property(obj, prop->name()) != 0;
 +}
 +
 +bool QQmlCompiler::buildProperty(QQmlScript::Property *prop,
 +                                         QQmlScript::Object *obj,
 +                                         const BindingContext &ctxt)
 +{
 +    if (prop->isEmpty()) 
 +        COMPILE_EXCEPTION(prop, tr("Empty property assignment"));
 +
 +    const QMetaObject *metaObject = obj->metaObject();
 +    Q_ASSERT(metaObject);
 +
 +    if (isAttachedPropertyName(prop->name())) {
 +        // Setup attached property data
 +
 +        if (ctxt.isSubContext()) {
 +            // Attached properties cannot be used on sub-objects.  Sub-objects
 +            // always exist in a binding sub-context, which is what we test
 +            // for here.
 +            COMPILE_EXCEPTION(prop, tr("Attached properties cannot be used here"));
 +        }
 +
 +        QQmlType *type = 0;
 +        QQmlImportedNamespace *typeNamespace = 0;
 +        unit->imports().resolveType(prop->name().toString(), &type, 0, 0, 0, &typeNamespace);
 +
 +        if (typeNamespace) {
 +            COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj, 
 +                                                   ctxt));
 +            return true;
 +        } else if (!type || !type->attachedPropertiesType())  {
 +            COMPILE_EXCEPTION(prop, tr("Non-existent attached object"));
 +        }
 +
 +        if (!prop->value)
 +            COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment"));
 +
 +        Q_ASSERT(type->attachedPropertiesFunction());
 +        prop->index = type->attachedPropertiesId();
 +        prop->value->metatype = type->attachedPropertiesType();
 +    } else {
 +        // Setup regular property data
 +        bool notInRevision = false;
 +        QQmlPropertyData *d =
 +            prop->name().isEmpty()?0:property(obj, prop->name(), &notInRevision);
 +
 +        if (d == 0 && notInRevision) {
 +            const QList<QQmlTypeData::TypeReference>  &resolvedTypes = unit->resolvedTypes();
 +            const QQmlTypeData::TypeReference &type = resolvedTypes.at(obj->type);
 +            if (type.type) {
 +                COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(elementName(obj)).arg(prop->name().toString()).arg(type.type->module()).arg(type.majorVersion).arg(type.minorVersion));
 +            } else {
 +                COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(elementName(obj)).arg(prop->name().toString()));
 +            }
 +        } else if (d) {
 +            prop->index = d->coreIndex;
 +            prop->core = *d;
 +        } else if (prop->isDefault) {
 +            QMetaProperty p = QQmlMetaType::defaultProperty(metaObject);
 +            QQmlPropertyData defaultPropertyData;
 +            defaultPropertyData.load(p, engine);
 +            if (p.name())
 +                prop->setName(QLatin1String(p.name()));
 +            prop->core = defaultPropertyData;
 +            prop->index = prop->core.coreIndex;
 +        }
 +
 +        // We can't error here as the "id" property does not require a
 +        // successful index resolution
 +        if (prop->index != -1) 
 +            prop->type = prop->core.propType;
 +
 +        // Check if this is an alias
 +        if (prop->index != -1 && 
 +            prop->parent && 
 +            prop->parent->type != -1 && 
 +            output->types.at(prop->parent->type).component) {
 +
 +            QQmlPropertyCache *cache = output->types.at(prop->parent->type).component->rootPropertyCache;
 +            if (cache && cache->property(prop->index) && cache->property(prop->index)->isAlias())
 +                prop->isAlias = true;
 +        }
 +
 +        if (prop->index != -1 && !prop->values.isEmpty()) 
 +            prop->parent->setBindingBit(prop->index);
 +    }
 +
 +    if (!prop->isDefault && prop->name() == id_string && !ctxt.isSubContext()) {
 +
 +        // The magic "id" behavior doesn't apply when "id" is resolved as a
 +        // default property or to sub-objects (which are always in binding
 +        // sub-contexts)
 +        COMPILE_CHECK(buildIdProperty(prop, obj));
 +        if (prop->type == QVariant::String &&
 +            prop->values.first()->value.isString())
 +            COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
 +
 +    } else if (isAttachedPropertyName(prop->name())) {
 +
 +        COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
 +
 +    } else if (prop->index == -1) {
 +
 +        if (prop->isDefault) {
 +            COMPILE_EXCEPTION(prop->values.first(), tr("Cannot assign to non-existent default property"));
 +        } else {
 +            COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString()));
 +        }
 +
 +    } else if (prop->value) {
 +
 +        COMPILE_CHECK(buildGroupedProperty(prop, obj, ctxt));
 +
 +    } else if (prop->core.isQList()) {
 +
 +        COMPILE_CHECK(buildListProperty(prop, obj, ctxt));
 +
 +    } else if (prop->type == qMetaTypeId<QQmlScriptString>()) {
 +
 +        COMPILE_CHECK(buildScriptStringProperty(prop, obj, ctxt));
 +
 +    } else {
 +
 +        COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
 +
 +    }
 +
 +    return true;
 +}
 +
 +bool QQmlCompiler::buildPropertyInNamespace(QQmlImportedNamespace *ns,
 +                                                    QQmlScript::Property *nsProp, 
 +                                                    QQmlScript::Object *obj, 
 +                                                    const BindingContext &ctxt)
 +{
 +    if (!nsProp->value)
 +        COMPILE_EXCEPTION(nsProp, tr("Invalid use of namespace"));
 +
 +    for (Property *prop = nsProp->value->properties.first(); prop; prop = nsProp->value->properties.next(prop)) {
 +
 +        if (!isAttachedPropertyName(prop->name()))
 +            COMPILE_EXCEPTION(prop, tr("Not an attached property name"));
 +
 +        // Setup attached property data
 +
 +        QQmlType *type = 0;
 +        unit->imports().resolveType(ns, prop->name().toString(), &type, 0, 0, 0);
 +
 +        if (!type || !type->attachedPropertiesType()) 
 +            COMPILE_EXCEPTION(prop, tr("Non-existent attached object"));
 +
 +        if (!prop->value)
 +            COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment"));
 +
 +        Q_ASSERT(type->attachedPropertiesFunction());
 +        prop->index = type->index();
 +        prop->value->metatype = type->attachedPropertiesType();
 +
 +        COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
 +    }
 +
 +    return true;
 +}
 +
 +void QQmlCompiler::genValueProperty(QQmlScript::Property *prop,
 +                                   QQmlScript::Object *obj)
 +{
 +    if (prop->core.isQList()) {
 +        genListProperty(prop, obj);
 +    } else {
 +        genPropertyAssignment(prop, obj);
 +    }
 +}
 +
 +void QQmlCompiler::genListProperty(QQmlScript::Property *prop,
 +                                  QQmlScript::Object *obj)
 +{
 +    int listType = enginePrivate->listType(prop->type);
 +
 +    Instruction::FetchQList fetch;
 +    fetch.property = prop->index;
 +    bool listTypeIsInterface = QQmlMetaType::isInterface(listType);
 +    fetch.type = listType;
 +    output->addInstruction(fetch);
 +
 +    for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
 +
 +        if (v->type == Value::CreatedObject) {
 +
 +            genObject(v->object);
 +            if (listTypeIsInterface) {
 +                Instruction::AssignObjectList assign;
 +                assign.line = prop->location.start.line;
 +                output->addInstruction(assign);
 +            } else {
 +                Instruction::StoreObjectQList store;
 +                output->addInstruction(store);
 +            }
 +
 +        } else if (v->type == Value::PropertyBinding) {
 +
 +            genBindingAssignment(v, prop, obj);
 +
 +        }
 +
 +    }
 +
 +    Instruction::PopQList pop;
 +    output->addInstruction(pop);
 +}
 +
 +void QQmlCompiler::genPropertyAssignment(QQmlScript::Property *prop,
 +                                        QQmlScript::Object *obj,
 +                                        QQmlScript::Property *valueTypeProperty)
 +{
 +    for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
 +
 +        Q_ASSERT(v->type == Value::CreatedObject ||
 +                 v->type == Value::PropertyBinding ||
 +                 v->type == Value::Literal);
 +
 +        if (v->type == Value::CreatedObject) {
 +
 +            genObject(v->object);
 +
 +            if (QQmlMetaType::isInterface(prop->type)) {
 +
 +                Instruction::StoreInterface store;
 +                store.line = v->object->location.start.line;
 +                store.propertyIndex = prop->index;
 +                output->addInstruction(store);
 +
 +            } else if (prop->type == QMetaType::QVariant) {
 +
 +                if (prop->core.isVMEProperty()) {
 +                    Instruction::StoreVarObject store;
 +                    store.line = v->object->location.start.line;
 +                    store.propertyIndex = prop->index;
 +                    output->addInstruction(store);
 +                } else {
 +                    Instruction::StoreVariantObject store;
 +                    store.line = v->object->location.start.line;
 +                    store.propertyIndex = prop->index;
 +                    output->addInstruction(store);
 +                }
 +
 +
 +            } else {
 +
 +                Instruction::StoreObject store;
 +                store.line = v->object->location.start.line;
 +                store.propertyIndex = prop->index;
 +                output->addInstruction(store);
 +
 +            }
 +        } else if (v->type == Value::PropertyBinding) {
 +
 +            genBindingAssignment(v, prop, obj, valueTypeProperty);
 +
 +        } else if (v->type == Value::Literal) {
 +
 +            genLiteralAssignment(prop, v);
 +
 +        }
 +
 +    }
 +
 +    for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
 +
 +        Q_ASSERT(v->type == Value::ValueSource ||
 +                 v->type == Value::ValueInterceptor);
 +
 +        if (v->type == Value::ValueSource) {
 +            genObject(v->object);
 +
 +            Instruction::StoreValueSource store;
 +            if (valueTypeProperty) {
 +                store.property = genValueTypeData(prop, valueTypeProperty);
 +                store.owner = 1;
 +            } else {
 +                store.property = prop->core;
 +                store.owner = 0;
 +            }
 +            QQmlType *valueType = toQmlType(v->object);
 +            store.castValue = valueType->propertyValueSourceCast();
 +            output->addInstruction(store);
 +
 +        } else if (v->type == Value::ValueInterceptor) {
 +            genObject(v->object);
 +
 +            Instruction::StoreValueInterceptor store;
 +            if (valueTypeProperty) {
 +                store.property = genValueTypeData(prop, valueTypeProperty);
 +                store.owner = 1;
 +            } else {
 +                store.property = prop->core;
 +                store.owner = 0;
 +            }
 +            QQmlType *valueType = toQmlType(v->object);
 +            store.castValue = valueType->propertyValueInterceptorCast();
 +            output->addInstruction(store);
 +        }
 +
 +    }
 +}
 +
 +bool QQmlCompiler::buildIdProperty(QQmlScript::Property *prop,
 +                                  QQmlScript::Object *obj)
 +{
 +    if (prop->value ||
 +        prop->values.isMany() ||
 +        prop->values.first()->object)
 +        COMPILE_EXCEPTION(prop, tr("Invalid use of id property"));
 +
 +    QQmlScript::Value *idValue = prop->values.first();
 +    QString val = idValue->primitive();
 +
 +    COMPILE_CHECK(checkValidId(idValue, val));
 +
 +    if (compileState->ids.value(val))
 +        COMPILE_EXCEPTION(prop, tr("id is not unique"));
 +
 +    prop->values.first()->type = Value::Id;
 +
 +    obj->id = val;
 +    addId(val, obj);
 +
 +    return true;
 +}
 +
 +void QQmlCompiler::addId(const QString &id, QQmlScript::Object *obj)
 +{
 +    Q_UNUSED(id);
 +    Q_ASSERT(!compileState->ids.value(id));
 +    Q_ASSERT(obj->id == id);
 +    obj->idIndex = compileState->ids.count();
 +    compileState->ids.append(obj);
 +}
 +
 +void QQmlCompiler::addBindingReference(JSBindingReference *ref)
 +{
 +    Q_ASSERT(ref->value && !ref->value->bindingReference);
 +    ref->value->bindingReference = ref;
 +    compileState->totalBindingsCount++;
 +    compileState->bindings.prepend(ref);
 +}
 +
 +void QQmlCompiler::saveComponentState()
 +{
 +    Q_ASSERT(compileState->root);
 +    Q_ASSERT(compileState->root->componentCompileState == 0);
 +
 +    compileState->root->componentCompileState = compileState;
 +
 +    if (componentStats) 
 +        componentStats->savedComponentStats.append(componentStats->componentStat);
 +}
 +
 +QQmlCompilerTypes::ComponentCompileState *
 +QQmlCompiler::componentState(QQmlScript::Object *obj)
 +{
 +    Q_ASSERT(obj->componentCompileState);
 +    return obj->componentCompileState;
 +}
 +
 +// Build attached property object.  In this example,
 +// Text {
 +//    GridView.row: 10
 +// }
 +// GridView is an attached property object.
 +bool QQmlCompiler::buildAttachedProperty(QQmlScript::Property *prop,
 +                                        QQmlScript::Object *obj,
 +                                        const BindingContext &ctxt)
 +{
 +    Q_ASSERT(prop->value);
 +    Q_ASSERT(prop->index != -1); // This is set in buildProperty()
 +
 +    compileState->objectDepth.push();
 +
 +    obj->addAttachedProperty(prop);
 +
 +    COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
 +
 +    compileState->objectDepth.pop();
 +
 +    return true;
 +}
 +
 +
 +// Build "grouped" properties. In this example:
 +// Text {
 +//     font.pointSize: 12
 +//     font.family: "Helvetica"
 +// }
 +// font is a nested property.  pointSize and family are not.
 +bool QQmlCompiler::buildGroupedProperty(QQmlScript::Property *prop,
 +                                                QQmlScript::Object *obj,
 +                                                const BindingContext &ctxt)
 +{
 +    Q_ASSERT(prop->type != 0);
 +    Q_ASSERT(prop->index != -1);
 +
 +    if (QQmlValueTypeFactory::isValueType(prop->type)) {
 +        if (prop->type >= 0 && enginePrivate->valueTypes[prop->type]) {
 +
 +            if (!prop->values.isEmpty()) {
 +                if (prop->values.first()->location < prop->value->location) {
 +                    COMPILE_EXCEPTION(prop->value, tr( "Property has already been assigned a value"));
 +                } else {
 +                    COMPILE_EXCEPTION(prop->values.first(), tr( "Property has already been assigned a value"));
 +                }
 +            }
 +
 +            if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration) {
 +                COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
 +            }
 +
 +
 +            if (prop->isAlias) {
 +                for (Property *vtProp = prop->value->properties.first(); vtProp; vtProp = prop->value->properties.next(vtProp)) {
 +                    vtProp->isAlias = true;
 +                }
 +            }
 +
 +            COMPILE_CHECK(buildValueTypeProperty(enginePrivate->valueTypes[prop->type],
 +                                                 prop->value, obj, ctxt.incr()));
 +            obj->addValueTypeProperty(prop);
 +        } else {
 +            COMPILE_EXCEPTION(prop, tr("Invalid grouped property access"));
 +        }
 +
 +    } else {
 +        // Load the nested property's meta type
 +        prop->value->metatype = enginePrivate->metaObjectForType(prop->type);
 +        if (!prop->value->metatype)
 +            COMPILE_EXCEPTION(prop, tr("Invalid grouped property access"));
 +
 +        if (!prop->values.isEmpty()) 
 +            COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign a value directly to a grouped property"));
 +
 +        obj->addGroupedProperty(prop);
 +
 +        compileState->objectDepth.push();
 +
 +        COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
 +
 +        compileState->objectDepth.pop();
 +    }
 +
 +    return true;
 +}
 +
 +bool QQmlCompiler::buildValueTypeProperty(QObject *type,
 +                                                  QQmlScript::Object *obj,
 +                                                  QQmlScript::Object *baseObj,
 +                                                  const BindingContext &ctxt)
 +{
 +    compileState->objectDepth.push();
 +
 +    if (obj->defaultProperty)
 +        COMPILE_EXCEPTION(obj, tr("Invalid property use"));
 +    obj->metatype = type->metaObject();
 +
 +    for (Property *prop = obj->properties.first(); prop; prop = obj->properties.next(prop)) {
 +
 +        QQmlPropertyData *d = property(obj, prop->name());
 +        if (d == 0) 
 +            COMPILE_EXCEPTION(prop, tr("Cannot assign to non-existent property \"%1\"").arg(prop->name().toString()));
 +
 +        prop->index = d->coreIndex;
 +        prop->type = d->propType;
 +        prop->core = *d;
 +        prop->isValueTypeSubProperty = true;
 +
 +        if (prop->value)
 +            COMPILE_EXCEPTION(prop, tr("Property assignment expected"));
 +
 +        if (prop->values.isMany()) {
 +            COMPILE_EXCEPTION(prop, tr("Single property assignment expected"));
 +        } else if (!prop->values.isEmpty()) {
 +            QQmlScript::Value *value = prop->values.first();
 +
 +            if (value->object) {
 +                COMPILE_EXCEPTION(prop, tr("Unexpected object assignment"));
 +            } else if (value->value.isScript()) {
 +                // ### Check for writability
 +
 +                //optimization for <Type>.<EnumValue> enum assignments
 +                bool isEnumAssignment = false;
 +
 +                if (prop->core.isEnum()) 
 +                    COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, value, &isEnumAssignment));
 +
 +                if (isEnumAssignment) {
 +                    value->type = Value::Literal;
 +                } else {
 +                    JSBindingReference *reference = pool->New<JSBindingReference>();
 +                    reference->expression = value->value;
 +                    reference->property = prop;
 +                    reference->value = value;
 +                    reference->bindingContext = ctxt;
 +                    reference->bindingContext.owner++;
 +                    addBindingReference(reference);
 +                    value->type = Value::PropertyBinding;
 +                }
 +            } else  {
 +                COMPILE_CHECK(testLiteralAssignment(prop, value));
 +                value->type = Value::Literal;
 +            }
 +        }
 +
 +        for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
 +            Q_ASSERT(v->object);
 +
 +            COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, baseObj, v, ctxt)); 
 +        }
 +
 +        obj->addValueProperty(prop);
 +    }
 +
 +    compileState->objectDepth.pop();
 +
 +    return true;
 +}
 +
 +// Build assignments to QML lists.  QML lists are properties of type
 +// QQmlListProperty<T>.  List properties can accept a list of 
 +// objects, or a single binding.
 +bool QQmlCompiler::buildListProperty(QQmlScript::Property *prop,
 +                                             QQmlScript::Object *obj,
 +                                             const BindingContext &ctxt)
 +{
 +    Q_ASSERT(prop->core.isQList());
 +
 +    compileState->listDepth.push();
 +
 +    int t = prop->type;
 +
 +    obj->addValueProperty(prop);
 +
 +    int listType = enginePrivate->listType(t);
 +    bool listTypeIsInterface = QQmlMetaType::isInterface(listType);
 +
 +    bool assignedBinding = false;
 +    for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
 +        if (v->object) {
 +            v->type = Value::CreatedObject;
 +            COMPILE_CHECK(buildObject(v->object, ctxt));
 +
 +            // We check object coercian here.  We check interface assignment
 +            // at runtime.
 +            if (!listTypeIsInterface) {
 +                if (!canCoerce(listType, v->object)) {
 +                    COMPILE_EXCEPTION(v, tr("Cannot assign object to list"));
 +                }
 +            }
 +
 +        } else if (v->value.isScript()) {
 +            if (assignedBinding)
 +                COMPILE_EXCEPTION(v, tr("Can only assign one binding to lists"));
 +
 +            assignedBinding = true;
 +            COMPILE_CHECK(buildBinding(v, prop, ctxt));
 +            v->type = Value::PropertyBinding;
 +        } else {
 +            COMPILE_EXCEPTION(v, tr("Cannot assign primitives to lists"));
 +        }
 +    }
 +
 +    compileState->listDepth.pop();
 +
 +    return true;
 +}
 +
 +// Compiles an assignment to a QQmlScriptString property
 +bool QQmlCompiler::buildScriptStringProperty(QQmlScript::Property *prop,
 +                                            QQmlScript::Object *obj,
 +                                            const BindingContext &ctxt)
 +{
 +    if (prop->values.isMany())
 +        COMPILE_EXCEPTION(prop->values.first()->nextValue, tr( "Cannot assign multiple values to a script property"));
 +
 +    if (prop->values.first()->object)
 +        COMPILE_EXCEPTION(prop->values.first(), tr( "Invalid property assignment: script expected"));
 +
 +    prop->scriptStringScope = ctxt.stack;
 +    obj->addScriptStringProperty(prop);
 +
 +    return true;
 +}
 +
 +// Compile regular property assignments of the form "property: <value>"
 +bool QQmlCompiler::buildPropertyAssignment(QQmlScript::Property *prop,
 +                                          QQmlScript::Object *obj,
 +                                          const BindingContext &ctxt)
 +{
 +    obj->addValueProperty(prop);
 +
 +    if (prop->values.isMany())
 +        COMPILE_EXCEPTION(prop->values.first(), tr( "Cannot assign multiple values to a singular property") );
 +
 +    for (Value *v = prop->values.first(); v; v = Property::ValueList::next(v)) {
 +        if (v->object) {
 +
 +            COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
 +
 +        } else {
 +
 +            COMPILE_CHECK(buildPropertyLiteralAssignment(prop, obj, v, ctxt));
 +
 +        }
 +    }
 +
 +    for (Value *v = prop->onValues.first(); v; v = Property::ValueList::next(v)) {
 +        Q_ASSERT(v->object);
 +        COMPILE_CHECK(buildPropertyOnAssignment(prop, obj, obj, v, ctxt));
 +    }
 +
 +    return true;
 +}
 +
 +// Compile assigning a single object instance to a regular property
 +bool QQmlCompiler::buildPropertyObjectAssignment(QQmlScript::Property *prop,
 +                                                         QQmlScript::Object *obj,
 +                                                         QQmlScript::Value *v,
 +                                                         const BindingContext &ctxt)
 +{
 +    Q_ASSERT(prop->index != -1);
 +    Q_ASSERT(v->object->type != -1);
 +
 +    if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration)
 +        COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
 +
 +    if (QQmlMetaType::isInterface(prop->type)) {
 +
 +        // Assigning an object to an interface ptr property
 +        COMPILE_CHECK(buildObject(v->object, ctxt));
 +
 +        v->type = Value::CreatedObject;
 +
 +    } else if (prop->type == QMetaType::QVariant) {
 +
 +        // Assigning an object to a QVariant
 +        COMPILE_CHECK(buildObject(v->object, ctxt));
 +
 +        v->type = Value::CreatedObject;
 +    } else {
 +        // Normally buildObject() will set this up, but we need the static
 +        // meta object earlier to test for assignability.  It doesn't matter
 +        // that there may still be outstanding synthesized meta object changes
 +        // on this type, as they are not relevant for assignability testing
 +        v->object->metatype = output->types.at(v->object->type).metaObject();
 +        Q_ASSERT(v->object->metaObject());
 +
 +        // We want to raw metaObject here as the raw metaobject is the
 +        // actual property type before we applied any extensions that might
 +        // effect the properties on the type, but don't effect assignability
 +        const QMetaObject *propertyMetaObject = enginePrivate->rawMetaObjectForType(prop->type);
 +
 +        // Will be true if the assgned type inherits propertyMetaObject
 +        bool isAssignable = false;
 +        // Determine isAssignable value
 +        if (propertyMetaObject) {
 +            const QMetaObject *c = v->object->metatype;
 +            while(c) {
 +                isAssignable |= (QQmlPropertyPrivate::equal(c, propertyMetaObject));
 +                c = c->superClass();
 +            }
 +        }
 +
 +        if (isAssignable) {
 +            // Simple assignment
 +            COMPILE_CHECK(buildObject(v->object, ctxt));
 +
 +            v->type = Value::CreatedObject;
 +        } else if (propertyMetaObject == &QQmlComponent::staticMetaObject) {
 +            // Automatic "Component" insertion
 +            QQmlScript::Object *root = v->object;
 +            QQmlScript::Object *component = pool->New<Object>();
 +            component->type = componentTypeRef();
 +            component->typeName = QStringLiteral("Qt/Component");
 +            component->metatype = &QQmlComponent::staticMetaObject;
 +            component->location = root->location;
 +            QQmlScript::Value *componentValue = pool->New<Value>();
 +            componentValue->object = root;
 +            component->getDefaultProperty()->addValue(componentValue);
 +            v->object = component;
 +            COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
 +        } else {
 +            COMPILE_EXCEPTION(v->object, tr("Cannot assign object to property"));
 +        }
 +    }
 +
 +    return true;
 +}
 +
 +// Compile assigning a single object instance to a regular property using the "on" syntax.
 +//
 +// For example:
 +//     Item {
 +//         NumberAnimation on x { }
 +//     }
 +bool QQmlCompiler::buildPropertyOnAssignment(QQmlScript::Property *prop,
 +                                                     QQmlScript::Object *obj,
 +                                                     QQmlScript::Object *baseObj,
 +                                                     QQmlScript::Value *v,
 +                                                     const BindingContext &ctxt)
 +{
 +    Q_ASSERT(prop->index != -1);
 +    Q_ASSERT(v->object->type != -1);
 +
 +    Q_UNUSED(obj);
 +
 +    if (!prop->core.isWritable())
 +        COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
 +
 +
 +    // Normally buildObject() will set this up, but we need the static
 +    // meta object earlier to test for assignability.  It doesn't matter
 +    // that there may still be outstanding synthesized meta object changes
 +    // on this type, as they are not relevant for assignability testing
 +    v->object->metatype = output->types.at(v->object->type).metaObject();
 +    Q_ASSERT(v->object->metaObject());
 +
 +    // Will be true if the assigned type inherits QQmlPropertyValueSource
 +    bool isPropertyValue = false;
 +    // Will be true if the assigned type inherits QQmlPropertyValueInterceptor
 +    bool isPropertyInterceptor = false;
 +    if (QQmlType *valueType = toQmlType(v->object)) {
 +        isPropertyValue = valueType->propertyValueSourceCast() != -1;
 +        isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1;
 +    }
 +
 +    if (isPropertyValue || isPropertyInterceptor) {
 +        // Assign as a property value source
 +        COMPILE_CHECK(buildObject(v->object, ctxt));
 +
 +        if (isPropertyInterceptor && prop->parent->synthdata.isEmpty())
 +            buildDynamicMeta(baseObj, ForceCreation);
 +        v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
 +    } else {
 +        COMPILE_EXCEPTION(v, tr("\"%1\" cannot operate on \"%2\"").arg(v->object->typeName).arg(prop->name().toString()));
 +    }
 +
 +    return true;
 +}
 +
 +// Compile assigning a literal or binding to a regular property
 +bool QQmlCompiler::buildPropertyLiteralAssignment(QQmlScript::Property *prop,
 +                                                          QQmlScript::Object *obj,
 +                                                          QQmlScript::Value *v,
 +                                                          const BindingContext &ctxt)
 +{
 +    Q_ASSERT(prop->index != -1);
 +
 +    if (v->value.isScript()) {
 +
 +        //optimization for <Type>.<EnumValue> enum assignments
 +        if (prop->core.isEnum()) {
 +            bool isEnumAssignment = false;
 +            COMPILE_CHECK(testQualifiedEnumAssignment(prop, obj, v, &isEnumAssignment));
 +            if (isEnumAssignment) {
 +                v->type = Value::Literal;
 +                return true;
 +            }
 +        }
 +
 +        // Test for other binding optimizations
 +        if (!buildLiteralBinding(v, prop, ctxt))
 +            COMPILE_CHECK(buildBinding(v, prop, ctxt));
 +
 +        v->type = Value::PropertyBinding;
 +
 +    } else {
 +
 +        COMPILE_CHECK(testLiteralAssignment(prop, v));
 +
 +        v->type = Value::Literal;
 +    }
 +
 +    return true;
 +}
 +
 +bool QQmlCompiler::testQualifiedEnumAssignment(QQmlScript::Property *prop,
 +                                                       QQmlScript::Object *obj,
 +                                                       QQmlScript::Value *v,
 +                                                       bool *isAssignment)
 +{
 +    *isAssignment = false;
 +    if (!prop->core.isEnum())
 +        return true;
 +
 +    QMetaProperty mprop = obj->metaObject()->property(prop->index);
 +
 +    if (!prop->core.isWritable() && !prop->isReadOnlyDeclaration)
 +        COMPILE_EXCEPTION(v, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
 +
 +    QString string = v->value.asString();
 +    if (!string.at(0).isUpper())
 +        return true;
 +
 +    QStringList parts = string.split(QLatin1Char('.'));
 +    if (parts.count() != 2)
 +        return true;
 +
 +    QString typeName = parts.at(0);
 +    QQmlType *type = 0;
 +    unit->imports().resolveType(typeName, &type, 0, 0, 0, 0);
 +
 +    //handle enums on value types (where obj->typeName is empty)
 +    QString objTypeName = obj->typeName;
 +    if (objTypeName.isEmpty()) {
 +        QQmlType *objType = toQmlType(obj);
 +        if (objType)
 +            objTypeName = objType->qmlTypeName();
 +    }
 +
 +    if (!type)
 +        return true;
 +
 +    QString enumValue = parts.at(1);
 +    int value;
 +    bool ok;
 +
 +    if (objTypeName == type->qmlTypeName()) {
 +        // When these two match, we can short cut the search
 +        if (mprop.isFlagType()) {
 +            value = mprop.enumerator().keysToValue(enumValue.toUtf8().constData(), &ok);
 +        } else {
 +            value = mprop.enumerator().keyToValue(enumValue.toUtf8().constData(), &ok);
 +        }
 +    } else {
 +        // Otherwise we have to search the whole type
 +        // This matches the logic in QV8TypeWrapper
 +        QByteArray enumName = enumValue.toUtf8();
 +        const QMetaObject *metaObject = type->baseMetaObject();
 +        ok = false;
 +        for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) {
 +            QMetaEnum e = metaObject->enumerator(ii);
 +            value = e.keyToValue(enumName.constData(), &ok);
 +        }
 +    }
 +
 +    if (!ok)
 +        return true;
 +
 +    v->type = Value::Literal;
 +    v->value = QQmlScript::Variant((double)value);
 +    *isAssignment = true;
 +
 +    return true;
 +}
 +
 +struct StaticQtMetaObject : public QObject
 +{
 +    static const QMetaObject *get()
 +        { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
 +};
 +
 +// Similar logic to above, but not knowing target property.
 +int QQmlCompiler::evaluateEnum(const QByteArray& script) const
 +{
 +    int dot = script.indexOf('.');
 +    if (dot > 0) {
 +        const QByteArray &scope = script.left(dot);
 +        QQmlType *type = 0;
 +        unit->imports().resolveType(QString::fromUtf8(script.left(dot)), &type, 0, 0, 0, 0);
 +        if (!type && scope != "Qt")
 +            return -1;
 +        const QMetaObject *mo = type ? type->metaObject() : StaticQtMetaObject::get();
 +        const char *key = script.constData() + dot+1;
 +        int i = mo->enumeratorCount();
 +        while (i--) {
 +            bool ok;
 +            int v = mo->enumerator(i).keyToValue(key, &ok);
 +            if (ok)
 +                return v;
 +        }
 +    }
 +    return -1;
 +}
 +
 +const QMetaObject *QQmlCompiler::resolveType(const QString& name) const
 +{
 +    QQmlType *qmltype = 0;
 +    if (!unit->imports().resolveType(name, &qmltype, 0, 0, 0, 0))
 +        return 0;
 +    if (!qmltype)
 +        return 0;
 +    return qmltype->metaObject();
 +}
 +
 +// similar to logic of completeComponentBuild, but also sticks data
 +// into primitives at the end
 +int QQmlCompiler::rewriteBinding(const QQmlScript::Variant& value, const QString& name)
 +{
 +    QQmlRewrite::RewriteBinding rewriteBinding;
 +    rewriteBinding.setName(QLatin1Char('$') + name.mid(name.lastIndexOf(QLatin1Char('.')) + 1));
 +
 +    QString rewrite = rewriteBinding(value.asAST(), value.asScript(), 0);
 +
 +    return output->indexForString(rewrite);
 +}
 +
 +QString QQmlCompiler::rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name)
 +{
 +    QQmlRewrite::RewriteSignalHandler rewriteSignalHandler;
 +    return rewriteSignalHandler(value.asAST(), value.asScript(), name);
 +}
 +
 +// Ensures that the dynamic meta specification on obj is valid
 +bool QQmlCompiler::checkDynamicMeta(QQmlScript::Object *obj)
 +{
 +    bool seenDefaultProperty = false;
 +
 +    // We use a coarse grain, 31 bit hash to check if there are duplicates.
 +    // Calculating the hash for the names is not a waste as we have to test
 +    // them against the illegalNames set anyway.
 +    QHashField propNames;
 +    QHashField methodNames;
 +
 +    // Check properties
 +    for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
 +        const QQmlScript::Object::DynamicProperty &prop = *p;
 +
 +        if (prop.isDefaultProperty) {
 +            if (seenDefaultProperty)
 +                COMPILE_EXCEPTION(&prop, tr("Duplicate default property"));
 +            seenDefaultProperty = true;
 +        }
 +
 +        if (propNames.testAndSet(prop.name.hash())) {
 +            for (Object::DynamicProperty *p2 = obj->dynamicProperties.first(); p2 != p; 
 +                 p2 = obj->dynamicProperties.next(p2)) {
 +                if (p2->name == prop.name) {
 +                    COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line,
 +                                               prop.nameLocation.column,
 +                                               tr("Duplicate property name"));
 +                }
 +            }
 +        }
 +
 +        if (prop.name.at(0).isUpper()) {
 +            COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line,
 +                                       prop.nameLocation.column,
 +                                       tr("Property names cannot begin with an upper case letter"));
 +        }
 +
 +        if (enginePrivate->v8engine()->illegalNames().contains(prop.name)) {
 +            COMPILE_EXCEPTION_LOCATION(prop.nameLocation.line,
 +                                       prop.nameLocation.column,
 +                                       tr("Illegal property name"));
 +        }
 +    }
 +
 +    for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
 +        const QQmlScript::Object::DynamicSignal &currSig = *s;
 +
 +        if (methodNames.testAndSet(currSig.name.hash())) {
 +            for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2 != s;
 +                 s2 = obj->dynamicSignals.next(s2)) {
 +                if (s2->name == currSig.name)
 +                    COMPILE_EXCEPTION(&currSig, tr("Duplicate signal name"));
 +            }
 +        }
 +
 +        if (currSig.name.at(0).isUpper())
 +            COMPILE_EXCEPTION(&currSig, tr("Signal names cannot begin with an upper case letter"));
 +        if (enginePrivate->v8engine()->illegalNames().contains(currSig.name))
 +            COMPILE_EXCEPTION(&currSig, tr("Illegal signal name"));
 +    }
 +
 +    for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
 +        const QQmlScript::Object::DynamicSlot &currSlot = *s;
 +
 +        if (methodNames.testAndSet(currSlot.name.hash())) {
 +            for (Object::DynamicSignal *s2 = obj->dynamicSignals.first(); s2;
 +                 s2 = obj->dynamicSignals.next(s2)) {
 +                if (s2->name == currSlot.name)
 +                    COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
 +            }
 +            for (Object::DynamicSlot *s2 = obj->dynamicSlots.first(); s2 != s;
 +                 s2 = obj->dynamicSlots.next(s2)) {
 +                if (s2->name == currSlot.name)
 +                    COMPILE_EXCEPTION(&currSlot, tr("Duplicate method name"));
 +            }
 +        }
 +
 +        if (currSlot.name.at(0).isUpper())
 +            COMPILE_EXCEPTION(&currSlot, tr("Method names cannot begin with an upper case letter"));
 +        if (enginePrivate->v8engine()->illegalNames().contains(currSlot.name))
 +            COMPILE_EXCEPTION(&currSlot, tr("Illegal method name"));
 +    }
 +
 +    return true;
 +}
 +
 +bool QQmlCompiler::mergeDynamicMetaProperties(QQmlScript::Object *obj)
 +{
 +    for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p;
 +         p = obj->dynamicProperties.next(p)) {
 +
 +        if (!p->defaultValue || p->type == Object::DynamicProperty::Alias)
 +            continue;
 +
 +        Property *property = 0;
 +        if (p->isDefaultProperty) {
 +            property = obj->getDefaultProperty();
 +        } else {
 +            property = obj->getProperty(p->name);
 +            if (!property->values.isEmpty()) 
 +                COMPILE_EXCEPTION(property, tr("Property value set multiple times"));
 +        }
 +
 +        if (p->isReadOnly)
 +            property->isReadOnlyDeclaration = true;
 +
 +        if (property->value)
 +            COMPILE_EXCEPTION(property, tr("Invalid property nesting"));
 +
 +        property->values.append(p->defaultValue->values);
 +    }
 +    return true;
 +}
 +
 +Q_GLOBAL_STATIC(QAtomicInt, classIndexCounter)
 +
 +bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode)
 +{
 +    Q_ASSERT(obj);
 +    Q_ASSERT(obj->metatype);
 +
 +    if (mode != ForceCreation &&
 +        obj->dynamicProperties.isEmpty() &&
 +        obj->dynamicSignals.isEmpty() &&
 +        obj->dynamicSlots.isEmpty())
 +        return true;
 +
 +    bool resolveAlias = (mode == ResolveAliases);
 +
 +    const Object::DynamicProperty *defaultProperty = 0;
 +    int aliasCount = 0;
 +    int varPropCount = 0;
 +    int totalPropCount = 0;
 +    int firstPropertyVarIndex = 0;
 +
 +    for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
 +
 +        if (p->type == Object::DynamicProperty::Alias)
 +            aliasCount++;
 +        if (p->type == Object::DynamicProperty::Var)
 +            varPropCount++;
 +
 +        if (p->isDefaultProperty && 
 +            (resolveAlias || p->type != Object::DynamicProperty::Alias))
 +            defaultProperty = p;
 +
 +        if (!resolveAlias) {
 +            // No point doing this for both the alias and non alias cases
 +            QQmlPropertyData *d = property(obj, p->name);
 +            if (d && d->isFinal())
 +                COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
 +        }
 +    }
 +
 +    bool buildData = resolveAlias || aliasCount == 0;
 +
 +    QByteArray dynamicData;
 +    if (buildData) {
 +        typedef QQmlVMEMetaData VMD;
 +
 +        dynamicData = QByteArray(sizeof(QQmlVMEMetaData) +
 +                                 (obj->dynamicProperties.count() - aliasCount) * sizeof(VMD::PropertyData) +
 +                                 obj->dynamicSlots.count() * sizeof(VMD::MethodData) +
 +                                 aliasCount * sizeof(VMD::AliasData), 0);
 +    }
 +
 +    int uniqueClassId = classIndexCounter()->fetchAndAddRelaxed(1);
 +
 +    QByteArray newClassName = obj->metatype->className();
 +    newClassName.append("_QML_");
 +    newClassName.append(QByteArray::number(uniqueClassId));
 +
 +    if (compileState->root == obj && !compileState->nested) {
 +        QString path = output->url.path();
 +        int lastSlash = path.lastIndexOf(QLatin1Char('/'));
 +        if (lastSlash > -1) {
 +            QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
 +            if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
 +                newClassName = nameBase.toUtf8() + "_QMLTYPE_" + QByteArray::number(uniqueClassId);
 +        }
 +    }
 +
 +    QFastMetaBuilder builder;
 +    QFastMetaBuilder::StringRef classNameRef = builder.init(newClassName.length(), 
 +            obj->dynamicProperties.count() - (resolveAlias?0:aliasCount),
 +            obj->dynamicSlots.count(),
 +            obj->dynamicSignals.count() + obj->dynamicProperties.count(),
 +            defaultProperty?1:0);
 +
 +    struct TypeData {
 +        Object::DynamicProperty::Type dtype;
 +        int metaType;
 +        const char *cppType;
 +    } builtinTypes[] = {
 +        { Object::DynamicProperty::Var, QMetaType::QVariant, "QVariant" },
 +        { Object::DynamicProperty::Variant, QMetaType::QVariant, "QVariant" },
 +        { Object::DynamicProperty::Int, QMetaType::Int, "int" },
 +        { Object::DynamicProperty::Bool, QMetaType::Bool, "bool" },
 +        { Object::DynamicProperty::Real, QMetaType::Double, "double" },
 +        { Object::DynamicProperty::String, QMetaType::QString, "QString" },
 +        { Object::DynamicProperty::Url, QMetaType::QUrl, "QUrl" },
 +        { Object::DynamicProperty::Color, QMetaType::QColor, "QColor" },
 +        { Object::DynamicProperty::Time, QMetaType::QTime, "QTime" },
 +        { Object::DynamicProperty::Date, QMetaType::QDate, "QDate" },
 +        { Object::DynamicProperty::DateTime, QMetaType::QDateTime, "QDateTime" },
 +    };
 +    static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
 +    QFastMetaBuilder::StringRef typeRefs[builtinTypeCount]; 
 +
 +    // Reserve dynamic properties
 +    if (obj->dynamicProperties.count()) {
 +        typedef QQmlVMEMetaData VMD;
 +
 +        int effectivePropertyIndex = 0;
 +        for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
 +
 +            // Reserve space for name
 +            p->nameRef = builder.newString(p->name.utf8length());
 +
 +            int propertyType = 0;
 +            bool readonly = false;
 +            QFastMetaBuilder::StringRef typeRef;
 +
 +            if (p->type == Object::DynamicProperty::Alias) {
 +                continue;
 +            } else if (p->type < builtinTypeCount) {
 +                Q_ASSERT(builtinTypes[p->type].dtype == p->type);
 +                propertyType = builtinTypes[p->type].metaType;
 +                if (typeRefs[p->type].isEmpty()) 
 +                    typeRefs[p->type] = builder.newString(strlen(builtinTypes[p->type].cppType));
 +                typeRef = typeRefs[p->type];
 +
 +            } else {
 +                Q_ASSERT(p->type == Object::DynamicProperty::CustomList ||
 +                         p->type == Object::DynamicProperty::Custom);
 +
 +                // XXX don't double resolve this in the case of an alias run
 +
 +                QByteArray customTypeName;
 +                QQmlType *qmltype = 0;
 +                QString url;
 +                if (!unit->imports().resolveType(p->customType.toString(), &qmltype, &url, 0, 0, 0))
 +                    COMPILE_EXCEPTION(p, tr("Invalid property type"));
 +
 +                if (!qmltype) {
 +                    QQmlTypeData *tdata = enginePrivate->typeLoader.get(QUrl(url));
 +                    Q_ASSERT(tdata);
 +                    Q_ASSERT(tdata->isComplete());
 +
 +                    QQmlCompiledData *data = tdata->compiledData();
 +                    customTypeName = data->root->className();
 +                    data->release();
 +                    tdata->release();
 +                } else {
 +                    customTypeName = qmltype->typeName();
 +                }
 +
 +                if (p->type == Object::DynamicProperty::Custom) {
 +                    customTypeName += '*';
 +                    propertyType = QMetaType::QObjectStar;
 +                } else {
 +                    readonly = true;
 +                    customTypeName = QByteArray("QQmlListProperty<") + customTypeName + QByteArray(">");
 +                    propertyType = qMetaTypeId<QQmlListProperty<QObject> >();
 +                }
 +
 +                p->resolvedCustomTypeName = pool->NewByteArray(customTypeName);
 +                p->typeRef = builder.newString(customTypeName.length());
 +                typeRef = p->typeRef;
 +            }
 +
 +            if (p->type == Object::DynamicProperty::Var)
 +                continue;
 +
 +            if (p->isReadOnly)
 +                readonly = true;
 +
 +            if (buildData) {
 +                VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
 +                vmd->propertyCount++;
 +                (vmd->propertyData() + effectivePropertyIndex)->propertyType = propertyType;
 +            }
 +
 +            if (p->type < builtinTypeCount)
 +                builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, (QMetaType::Type)propertyType, 
 +                                    readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable, 
 +                                    effectivePropertyIndex);
 +            else 
 +                builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef, 
 +                                    readonly?QFastMetaBuilder::None:QFastMetaBuilder::Writable, 
 +                                    effectivePropertyIndex);
 +
 +            p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
 +            builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
 +
 +            effectivePropertyIndex++;
 +        }
 +
 +        if (varPropCount) {
 +            VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
 +            if (buildData)
 +                vmd->varPropertyCount = varPropCount;
 +            firstPropertyVarIndex = effectivePropertyIndex;
 +            totalPropCount = varPropCount + effectivePropertyIndex;
 +            for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
 +                if (p->type == Object::DynamicProperty::Var) {
 +                    QFastMetaBuilder::StringRef typeRef = typeRefs[p->type];
 +                    if (buildData) {
 +                        vmd->propertyCount++;
 +                        (vmd->propertyData() + effectivePropertyIndex)->propertyType = QMetaType::QVariant;
 +                    }
 +
 +                    builder.setProperty(effectivePropertyIndex, p->nameRef, typeRef,
 +                                        QMetaType::QVariant,
 +                                        p->isReadOnly?QFastMetaBuilder::None:QFastMetaBuilder::Writable,
 +                                        effectivePropertyIndex);
 +
 +                    p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
 +                    builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
 +
 +                    effectivePropertyIndex++;
 +                }
 +            }
 +        }
 +        
 +        if (aliasCount) {
 +            int aliasIndex = 0;
 +            for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
 +                if (p->type == Object::DynamicProperty::Alias) {
 +                    if (resolveAlias) {
 +                        Q_ASSERT(buildData);
 +                        ((QQmlVMEMetaData *)dynamicData.data())->aliasCount++;
 +                        COMPILE_CHECK(compileAlias(builder, dynamicData, obj, effectivePropertyIndex, 
 +                                                   aliasIndex, *p));
 +                    }
 +                    // Even if we aren't resolving the alias, we need a fake signal so that the 
 +                    // metaobject remains consistent across the resolve and non-resolve alias runs
 +                    p->changedSignatureRef = builder.newString(p->name.utf8length() + strlen("Changed()"));
 +                    builder.setSignal(effectivePropertyIndex, p->changedSignatureRef);
 +                    effectivePropertyIndex++;
 +                    aliasIndex++;
 +                }
 +            }
 +        }
 +    }
 +
 +    // Reserve default property
 +    QFastMetaBuilder::StringRef defPropRef;
 +    if (defaultProperty) {
 +        defPropRef = builder.newString(strlen("DefaultProperty"));
 +        builder.setClassInfo(0, defPropRef, defaultProperty->nameRef);
 +    }
 +
 +    // Reserve dynamic signals
 +    int signalIndex = 0;
 +    for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
 +
 +        int paramCount = s->parameterNames.count();
 +
 +        int signatureSize = s->name.utf8length() + 2 /* paren */;
 +        int namesSize = 0;
 +        if (paramCount) signatureSize += s->parameterTypesLength() + (paramCount - 1) /* commas */;
 +        if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1) /* commas */;
 +
 +        s->signatureRef = builder.newString(signatureSize);
 +        if (namesSize) s->parameterNamesRef = builder.newString(namesSize);
 +
 +        if (buildData)
 +            ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
 +        
 +        builder.setSignal(signalIndex + obj->dynamicProperties.count(), s->signatureRef, s->parameterNamesRef);
 +        ++signalIndex;
 +    }
 +
 +    // Reserve dynamic slots
 +    if (obj->dynamicSlots.count()) {
 +
 +        // Allocate QVariant string
 +        if (typeRefs[0].isEmpty()) 
 +            typeRefs[0] = builder.newString(strlen(builtinTypes[0].cppType));
 +
 +        typedef QQmlVMEMetaData VMD;
 +
 +        int methodIndex = 0;
 +        for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
 +            int paramCount = s->parameterNames.count();
 +
 +            int signatureSize = s->name.utf8length() + 2 /* paren */;
 +            int namesSize = 0; 
 +            if (paramCount) signatureSize += (paramCount * strlen("QVariant") + (paramCount - 1));
 +            if (paramCount) namesSize += s->parameterNamesLength() + (paramCount - 1 /* commas */); 
 +
 +            s->signatureRef = builder.newString(signatureSize);
 +            if (namesSize) s->parameterNamesRef = builder.newString(namesSize);
 +
 +            builder.setMethod(methodIndex, s->signatureRef, s->parameterNamesRef, typeRefs[0]);
 +
 +            if (buildData) {
 +                QString funcScript;
 +                funcScript.reserve(strlen("(function ") + s->name.length() + 1 /* lparen */ + 
 +                        namesSize + 1 /* rparen */ + s->body.length() + 1 /* rparen */);
 +                funcScript = QLatin1String("(function ") + s->name.toString() + QLatin1Char('(');
 +                for (int jj = 0; jj < paramCount; ++jj) {
 +                    if (jj) funcScript.append(QLatin1Char(','));
 +                    funcScript.append(QLatin1String(s->parameterNames.at(jj)));
 +                }
 +                funcScript += QLatin1Char(')') + s->body + QLatin1Char(')');
 +
 +                QByteArray utf8 = funcScript.toUtf8();
 +                VMD::MethodData methodData = { s->parameterNames.count(), 0, 
 +                                               utf8.length(),
 +                                               s->location.start.line };
 +
 +                VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
 +                vmd->methodCount++;
 +
 +                VMD::MethodData &md = *(vmd->methodData() + methodIndex);
 +                md = methodData;
 +                md.bodyOffset = dynamicData.size();
 +
 +                dynamicData.append((const char *)utf8.constData(), utf8.length());
 +            }
 +
 +
 +            methodIndex++;
 +        }
 +    }
 +
 +    // Now allocate used builtin types
 +    for (int ii = 0; ii < builtinTypeCount; ++ii) {
 +        if (!typeRefs[ii].isEmpty())
 +            typeRefs[ii].load(builtinTypes[ii].cppType);
 +    }
 +
 +    // Now allocate properties
 +    for (Object::DynamicProperty *p = obj->dynamicProperties.first(); p; p = obj->dynamicProperties.next(p)) {
 +
 +        char *d = p->changedSignatureRef.data();
 +        p->name.writeUtf8(d);
 +        strcpy(d + p->name.utf8length(), "Changed()");
 +
 +        if (p->type == Object::DynamicProperty::Alias && !resolveAlias)
 +            continue;
 +
 +        p->nameRef.load(p->name);
 +
 +        if (p->type >= builtinTypeCount) {
 +            Q_ASSERT(p->resolvedCustomTypeName);
 +            p->typeRef.load(*p->resolvedCustomTypeName);
 +        }
 +    }
 +
 +    // Allocate default property if necessary
 +    if (defaultProperty) 
 +        strcpy(defPropRef.data(), "DefaultProperty");
 +
 +    // Now allocate signals
 +    for (Object::DynamicSignal *s = obj->dynamicSignals.first(); s; s = obj->dynamicSignals.next(s)) {
 +
 +        char *d = s->signatureRef.data();
 +        char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data();
 +        s->name.writeUtf8(d); d += s->name.utf8length();
 +        *d++ = '('; 
 +
 +        for (int jj = 0; jj < s->parameterNames.count(); ++jj) {
 +            if (jj != 0) { *d++ = ','; *d2++ = ','; }
 +            strcpy(d, s->parameterTypes.at(jj).constData());
 +            d += s->parameterTypes.at(jj).length();
 +            s->parameterNames.at(jj).writeUtf8(d2);
 +            d2 += s->parameterNames.at(jj).utf8length();
 +        }
 +        *d++ = ')';
 +        *d = 0;
 +        if (d2) *d2 = 0;
 +    }
 +
 +    // Now allocate methods
 +    for (Object::DynamicSlot *s = obj->dynamicSlots.first(); s; s = obj->dynamicSlots.next(s)) {
 +        char *d = s->signatureRef.data();
 +        char *d2 = s->parameterNamesRef.isEmpty()?0:s->parameterNamesRef.data();
 +        s->name.writeUtf8(d); d += s->name.utf8length();
 +        *d++ = '('; 
 +        for (int jj = 0; jj < s->parameterNames.count(); ++jj) {
 +            if (jj != 0) { *d++ = ','; *d2++ = ','; }
 +            strcpy(d, "QVariant");
 +            d += strlen("QVariant");
 +            strcpy(d2, s->parameterNames.at(jj).constData());
 +            d2 += s->parameterNames.at(jj).length();
 +        }
 +        *d++ = ')';
 +        *d = 0;
 +        if (d2) *d2 = 0;
 +    }
 +
 +    // Now allocate class name
 +    classNameRef.load(newClassName);
 +
 +    obj->metadata = builder.toData();
 +    builder.fromData(&obj->extObject, obj->metatype, obj->metadata);
 +
 +    if (mode == IgnoreAliases && aliasCount) 
 +        compileState->aliasingObjects.append(obj);
 +
 +    obj->synthdata = dynamicData;
 +
 +    if (obj->synthCache) {
 +        obj->synthCache->release();
 +        obj->synthCache = 0;
 +    }
 +
 +    if (obj->type != -1) {
 +        QQmlPropertyCache *superCache = output->types[obj->type].createPropertyCache(engine);
 +        QQmlPropertyCache *cache =
 +            superCache->copyAndAppend(engine, &obj->extObject,
 +                                      QQmlPropertyData::NoFlags,
 +                                      QQmlPropertyData::IsVMEFunction,
 +                                      QQmlPropertyData::IsVMESignal);
 +
 +        // now we modify the flags appropriately for var properties.
 +        int propertyOffset = obj->extObject.propertyOffset();
 +        QQmlPropertyData *currPropData = 0;
 +        for (int pvi = firstPropertyVarIndex; pvi < totalPropCount; ++pvi) {
 +            currPropData = cache->property(pvi + propertyOffset);
 +            currPropData->setFlags(currPropData->getFlags() | QQmlPropertyData::IsVMEProperty);
 +        }
 +
 +        obj->synthCache = cache;
 +    }
 +
 +    return true;
 +}
 +
 +bool QQmlCompiler::checkValidId(QQmlScript::Value *v, const QString &val)
 +{
 +    if (val.isEmpty()) 
 +        COMPILE_EXCEPTION(v, tr( "Invalid empty ID"));
 +
 +    QChar ch = val.at(0);
 +    if (ch.isLetter() && !ch.isLower())
 +        COMPILE_EXCEPTION(v, tr( "IDs cannot start with an uppercase letter"));
 +
 +    QChar u(QLatin1Char('_'));
 +    if (!ch.isLetter() && ch != u)
 +        COMPILE_EXCEPTION(v, tr( "IDs must start with a letter or underscore"));
 +
 +    for (int ii = 1; ii < val.count(); ++ii) {
 +        ch = val.at(ii);
 +        if (!ch.isLetterOrNumber() && ch != u)
 +            COMPILE_EXCEPTION(v, tr( "IDs must contain only letters, numbers, and underscores"));
 +    }
 +
 +    if (enginePrivate->v8engine()->illegalNames().contains(val))
 +        COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
 +
 +    return true;
 +}
 +
 +#include <private/qqmljsparser_p.h>
 +
 +static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
 +{
 +    if (node->kind == QQmlJS::AST::Node::Kind_IdentifierExpression) {
 +        QString name =
 +            static_cast<QQmlJS::AST::IdentifierExpression *>(node)->name.toString();
 +        return QStringList() << name;
 +    } else if (node->kind == QQmlJS::AST::Node::Kind_FieldMemberExpression) {
 +        QQmlJS::AST::FieldMemberExpression *expr = static_cast<QQmlJS::AST::FieldMemberExpression *>(node);
 +
 +        QStringList rv = astNodeToStringList(expr->base);
 +        if (rv.isEmpty())
 +            return rv;
 +        rv.append(expr->name.toString());
 +        return rv;
 +    }
 +    return QStringList();
 +}
 +
 +bool QQmlCompiler::compileAlias(QFastMetaBuilder &builder,
 +                                        QByteArray &data,
 +                                        QQmlScript::Object *obj,
 +                                        int propIndex, int aliasIndex,
 +                                        Object::DynamicProperty &prop)
 +{
 +    if (!prop.defaultValue)
 +        COMPILE_EXCEPTION(obj, tr("No property alias location"));
 +
 +    if (!prop.defaultValue->values.isOne() ||
 +        prop.defaultValue->values.first()->object ||
 +        !prop.defaultValue->values.first()->value.isScript())
 +        COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
 +
 +    QQmlJS::AST::Node *node = prop.defaultValue->values.first()->value.asAST();
 +    if (!node)
 +        COMPILE_EXCEPTION(obj, tr("No property alias location")); // ### Can this happen?
 +
 +    QStringList alias = astNodeToStringList(node);
 +
 +    if (alias.count() < 1 || alias.count() > 3)
 +        COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
 +
 +    QQmlScript::Object *idObject = compileState->ids.value(alias.at(0));
 +    if (!idObject)
 +        COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias reference. Unable to find id \"%1\"").arg(alias.at(0)));
 +
 +    QByteArray typeName;
 +
 +    int propIdx = -1;
 +    int flags = 0;
 +    int type = 0;
 +    bool writable = false;
 +    bool resettable = false;
 +    if (alias.count() == 2 || alias.count() == 3) {
 +        propIdx = indexOfProperty(idObject, alias.at(1));
 +
 +        if (-1 == propIdx) {
 +            COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
 +        } else if (propIdx > 0xFFFF) {
 +            COMPILE_EXCEPTION(prop.defaultValue, tr("Alias property exceeds alias bounds"));
 +        }
 +
 +        QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx);
 +        if (!aliasProperty.isScriptable())
 +            COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
 +
 +        writable = aliasProperty.isWritable() && !prop.isReadOnly;
 +        resettable = aliasProperty.isResettable() && !prop.isReadOnly;
 +
 +        if (aliasProperty.type() < QVariant::UserType
 +            || uint(aliasProperty.type()) == QMetaType::QVariant)
 +            type = aliasProperty.type();
 +
 +        if (alias.count() == 3) {
 +            QQmlValueType *valueType = enginePrivate->valueTypes[aliasProperty.type()];
 +            if (!valueType)
 +                COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
 +
 +            propIdx |= ((unsigned int)aliasProperty.type()) << 24;
 +
 +            int valueTypeIndex = valueType->metaObject()->indexOfProperty(alias.at(2).toUtf8().constData());
 +            if (valueTypeIndex == -1)
 +                COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location"));
 +            Q_ASSERT(valueTypeIndex <= 0xFF);
 +            
 +            aliasProperty = valueType->metaObject()->property(valueTypeIndex);
 +            propIdx |= (valueTypeIndex << 16);
 +
 +            // update the property type
 +            type = aliasProperty.type();
 +            if (type >= (int)QVariant::UserType)
 +                type = 0;
 +        }
 +
 +        if (aliasProperty.isEnumType()) 
 +            typeName = "int";  // Avoid introducing a dependency on the aliased metaobject
 +        else
 +            typeName = aliasProperty.typeName();
 +    } else {
 +        Q_ASSERT(idObject->type != -1); // How else did it get an id?
 +
 +        const QQmlCompiledData::TypeReference &ref = output->types.at(idObject->type);
 +        if (ref.type)
 +            typeName = ref.type->typeName();
 +        else
 +            typeName = ref.component->root->className();
 +
 +        typeName += '*';
 +    }
 +
 +    if (typeName.endsWith('*'))
 +        flags |= QML_ALIAS_FLAG_PTR;
 +
 +    QQmlVMEMetaData::AliasData aliasData = { idObject->idIndex, propIdx, flags };
 +
 +    typedef QQmlVMEMetaData VMD;
 +    VMD *vmd = (QQmlVMEMetaData *)data.data();
 +    *(vmd->aliasData() + aliasIndex) = aliasData;
 +
 +    prop.nameRef = builder.newString(prop.name.utf8length());
 +    prop.resolvedCustomTypeName = pool->NewByteArray(typeName);
 +    prop.typeRef = builder.newString(typeName.length());
 +
 +    int propertyFlags = 0;
 +    if (writable)
 +        propertyFlags |= QFastMetaBuilder::Writable;
 +    if (resettable)
 +        propertyFlags |= QFastMetaBuilder::Resettable;
 +
 +    builder.setProperty(propIndex, prop.nameRef, prop.typeRef, (QMetaType::Type)type, 
 +                        (QFastMetaBuilder::PropertyFlag)propertyFlags,
 +                        propIndex);
 +
 +    return true;
 +}
 +
 +bool QQmlCompiler::buildBinding(QQmlScript::Value *value,
 +                                        QQmlScript::Property *prop,
 +                                        const BindingContext &ctxt)
 +{
 +    Q_ASSERT(prop->index != -1);
 +    Q_ASSERT(prop->parent);
 +    Q_ASSERT(prop->parent->metaObject());
 +
 +    if (!prop->core.isWritable() && !prop->core.isQList() && !prop->isReadOnlyDeclaration)
 +        COMPILE_EXCEPTION(prop, tr("Invalid property assignment: \"%1\" is a read-only property").arg(prop->name().toString()));
 +
 +    JSBindingReference *reference = pool->New<JSBindingReference>();
 +    reference->expression = value->value;
 +    reference->property = prop;
 +    reference->value = value;
 +    reference->bindingContext = ctxt;
 +    addBindingReference(reference);
 +
 +    return true;
 +}
 +
 +bool QQmlCompiler::buildLiteralBinding(QQmlScript::Value *v,
 +                                               QQmlScript::Property *prop,
 +                                               const QQmlCompilerTypes::BindingContext &)
 +{
 +    Q_ASSERT(v->value.isScript());
 +
 +    if (!prop->core.isWritable())
 +        return false;
 +
 +    AST::Node *binding = v->value.asAST();
 +
 +    if (prop->type == QVariant::String) {
 +        if (AST::CallExpression *e = AST::cast<AST::CallExpression *>(binding)) {
 +            if (AST::IdentifierExpression *i = AST::cast<AST::IdentifierExpression *>(e->base)) {
 +                if (i->name == qsTrId_string) {
 +                    AST::ArgumentList *arg1 = e->arguments?e->arguments:0;
 +                    AST::ArgumentList *arg2 = arg1?arg1->next:0;
 +
 +                    if (arg1 && arg1->expression->kind == AST::Node::Kind_StringLiteral &&
 +                        (!arg2 || arg2->expression->kind == AST::Node::Kind_NumericLiteral) &&
 +                        (!arg2 || !arg2->next)) {
 +
 +                        QStringRef text;
 +                        int n = -1;
 +
 +                        text = AST::cast<AST::StringLiteral *>(arg1->expression)->value;
 +                        if (arg2) n = (int)AST::cast<AST::NumericLiteral *>(arg2->expression)->value;
 +
 +                        TrBindingReference *reference = pool->New<TrBindingReference>();
 +                        reference->dataType = BindingReference::TrId;
 +                        reference->text = text;
 +                        reference->n = n;
 +                        v->bindingReference = reference;
 +                        return true;
 +                    }
 +
 +                } else if (i->name == qsTr_string) {
 +
 +                    AST::ArgumentList *arg1 = e->arguments?e->arguments:0;
 +                    AST::ArgumentList *arg2 = arg1?arg1->next:0;
 +                    AST::ArgumentList *arg3 = arg2?arg2->next:0;
 +
 +                    if (arg1 && arg1->expression->kind == AST::Node::Kind_StringLiteral &&
 +                        (!arg2 || arg2->expression->kind == AST::Node::Kind_StringLiteral) &&
 +                        (!arg3 || arg3->expression->kind == AST::Node::Kind_NumericLiteral) &&
 +                        (!arg3 || !arg3->next)) {
 +
 +                        QStringRef text;
 +                        QStringRef comment;
 +                        int n = -1;
 +
 +                        text = AST::cast<AST::StringLiteral *>(arg1->expression)->value;
 +                        if (arg2) comment = AST::cast<AST::StringLiteral *>(arg2->expression)->value;
 +                        if (arg3) n = (int)AST::cast<AST::NumericLiteral *>(arg3->expression)->value;
 +
 +                        TrBindingReference *reference = pool->New<TrBindingReference>();
 +                        reference->dataType = BindingReference::Tr;
 +                        reference->text = text;
 +                        reference->comment = comment;
 +                        reference->n = n;
 +                        v->bindingReference = reference;
 +                        return true;
 +                    }
 +
 +                }
 +            }
 +        }
 +
 +    }
 +
 +    return false;
 +}
 +
 +void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding,
 +                                                QQmlScript::Property *prop,
 +                                                QQmlScript::Object *obj,
 +                                                QQmlScript::Property *valueTypeProperty)
 +{
 +    Q_UNUSED(obj);
 +    Q_ASSERT(binding->bindingReference);
 +
 +    const BindingReference &ref = *binding->bindingReference;
 +    if (ref.dataType == BindingReference::TrId) {
 +        const TrBindingReference &tr = static_cast<const TrBindingReference &>(ref);
 +
 +        Instruction::StoreTrIdString store;
 +        store.propertyIndex = prop->core.coreIndex;
 +        store.text = output->indexForByteArray(tr.text.toUtf8());
 +        store.n = tr.n;
 +        output->addInstruction(store);
 +    } else if (ref.dataType == BindingReference::Tr) {
 +        const TrBindingReference &tr = static_cast<const TrBindingReference &>(ref);
 +
 +        Instruction::StoreTrString store;
 +        store.propertyIndex = prop->core.coreIndex;
 +        store.context = translationContextIndex();
 +        store.text = output->indexForByteArray(tr.text.toUtf8());
 +        store.comment = output->indexForByteArray(tr.comment.toUtf8());
 +        store.n = tr.n;
 +        output->addInstruction(store);
 +    } else if (ref.dataType == BindingReference::V4) {
 +        const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
 +
 +        Instruction::StoreV4Binding store;
 +        store.value = js.compiledIndex;
 +        store.context = js.bindingContext.stack;
 +        store.owner = js.bindingContext.owner;
 +        if (valueTypeProperty) {
 +            store.property = (valueTypeProperty->index & 0xFFFF) |
 +                             ((valueTypeProperty->type & 0xFF)) << 16 |
 +                             ((prop->index & 0xFF) << 24);
 +            store.isRoot = (compileState->root == valueTypeProperty->parent);
 +        } else {
 +            store.property = prop->index;
 +            store.isRoot = (compileState->root == obj);
 +        }
 +        store.line = binding->location.start.line;
 +        store.column = binding->location.start.column;
 +        output->addInstruction(store);
 +    } else if (ref.dataType == BindingReference::V8) {
 +        const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
 +
 +        Instruction::StoreV8Binding store;
 +        store.value = js.compiledIndex;
 +        store.context = js.bindingContext.stack;
 +        store.owner = js.bindingContext.owner;
 +        if (valueTypeProperty) {
 +            store.isRoot = (compileState->root == valueTypeProperty->parent);
 +        } else {
 +            store.isRoot = (compileState->root == obj);
 +        }
 +        store.line = binding->location.start.line;
 +        store.column = binding->location.start.column;
 +
 +        Q_ASSERT(js.bindingContext.owner == 0 ||
 +                 (js.bindingContext.owner != 0 && valueTypeProperty));
 +        if (js.bindingContext.owner) {
 +            store.property = genValueTypeData(prop, valueTypeProperty);
 +        } else {
 +            store.property = prop->core;
 +        }
 +
 +        output->addInstruction(store);
 +    } else if (ref.dataType == BindingReference::QtScript) {
 +        const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
 +
 +        QQmlInstruction store;
 +        store.assignBinding.value = output->indexForString(js.rewrittenExpression);
 +        store.assignBinding.context = js.bindingContext.stack;
 +        store.assignBinding.owner = js.bindingContext.owner;
 +        store.assignBinding.line = binding->location.start.line;
 +        store.assignBinding.column = binding->location.start.column;
 +
 +        if (valueTypeProperty) {
 +            store.assignBinding.isRoot = (compileState->root == valueTypeProperty->parent);
 +        } else {
 +            store.assignBinding.isRoot = (compileState->root == obj);
 +        }
 +
 +        Q_ASSERT(js.bindingContext.owner == 0 ||
 +                 (js.bindingContext.owner != 0 && valueTypeProperty));
 +        if (js.bindingContext.owner) {
 +            store.assignBinding.property = genValueTypeData(prop, valueTypeProperty);
 +        } else {
 +            store.assignBinding.property = prop->core;
 +        }
 +        output->addInstructionHelper(
 +            !prop->isAlias ? QQmlInstruction::StoreBinding
 +                           : QQmlInstruction::StoreBindingOnAlias
 +            , store);
 +    } else {
 +        Q_ASSERT(!"Unhandled BindingReference::DataType type");
 +    }
 +}
 +
 +int QQmlCompiler::genContextCache()
 +{
 +    if (compileState->ids.count() == 0)
 +        return -1;
 +
 +    QQmlIntegerCache *cache = new QQmlIntegerCache();
 +    cache->reserve(compileState->ids.count());
 +    for (Object *o = compileState->ids.first(); o; o = compileState->ids.next(o)) 
 +        cache->add(o->id, o->idIndex);
 +
 +    output->contextCaches.append(cache);
 +    return output->contextCaches.count() - 1;
 +}
 +
 +QQmlPropertyData
 +QQmlCompiler::genValueTypeData(QQmlScript::Property *valueTypeProp, 
 +                                       QQmlScript::Property *prop)
 +{
 +    typedef QQmlPropertyPrivate QDPP;
 +    return QDPP::saveValueType(prop->parent->metaObject(), prop->index, 
 +                               enginePrivate->valueTypes[prop->type]->metaObject(), 
 +                               valueTypeProp->index, engine);
 +}
 +
 +bool QQmlCompiler::completeComponentBuild()
 +{
 +    if (componentStats)
 +        componentStats->componentStat.ids = compileState->ids.count();
 +
 +    for (Object *aliasObject = compileState->aliasingObjects.first(); aliasObject; 
 +         aliasObject = compileState->aliasingObjects.next(aliasObject)) 
 +        COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases));
 +
 +    QV4Compiler::Expression expr(unit->imports());
 +    expr.component = compileState->root;
 +    expr.ids = &compileState->ids;
 +    expr.importCache = output->importCache;
 +
 +    QV4Compiler bindingCompiler;
 +
 +    QList<JSBindingReference*> sharedBindings;
 +
 +    for (JSBindingReference *b = compileState->bindings.first(); b; b = b->nextReference) {
 +
 +        JSBindingReference &binding = *b;
 +
 +        // ### We don't currently optimize for bindings on alias's - because 
 +        // of the solution to QTBUG-13719
 +        if (!binding.property->isAlias) {
 +            expr.context = binding.bindingContext.object;
 +            expr.property = binding.property;
 +            expr.expression = binding.expression;
 +
 +            int index = bindingCompiler.compile(expr, enginePrivate);
 +            if (index != -1) {
 +                binding.dataType = BindingReference::V4;
 +                binding.compiledIndex = index;
 +                if (componentStats)
 +                    componentStats->componentStat.optimizedBindings.append(b->value->location);
 +                continue;
 +            } 
 +        }
 +
 +        // Pre-rewrite the expression
 +        QString expression = binding.expression.asScript();
 +
 +        QQmlRewrite::RewriteBinding rewriteBinding;
 +        rewriteBinding.setName(QLatin1Char('$')+binding.property->name().toString());
 +        bool isSharable = false;
 +        binding.rewrittenExpression = rewriteBinding(binding.expression.asAST(), expression, &isSharable);
 +
-         }
++        if (isSharable && !binding.property->isAlias /* See above re alias */ &&
 +            binding.property->type != qMetaTypeId<QQmlBinding*>()) {
 +            binding.dataType = BindingReference::V8;
 +            sharedBindings.append(b);
++
++            if (componentStats)
++                componentStats->componentStat.sharedBindings.append(b->value->location);
 +        } else {
 +            binding.dataType = BindingReference::QtScript;
-         if (componentStats)
-             componentStats->componentStat.scriptBindings.append(b->value->location);
 +
++            if (componentStats)
++                componentStats->componentStat.scriptBindings.append(b->value->location);
++        }
 +    }
 +
 +    if (!sharedBindings.isEmpty()) {
 +        struct Sort {
 +            static bool lt(const JSBindingReference *lhs, const JSBindingReference *rhs)
 +            {
 +                return lhs->value->location.start.line < rhs->value->location.start.line;
 +            }
 +        };
 +
 +        qSort(sharedBindings.begin(), sharedBindings.end(), Sort::lt);
 +
 +        int startLineNumber = sharedBindings.at(0)->value->location.start.line;
 +        int lineNumber = startLineNumber;
 +
 +        QByteArray functionArray("[", 1);
 +        for (int ii = 0; ii < sharedBindings.count(); ++ii) {
 +
 +            JSBindingReference *reference = sharedBindings.at(ii);
 +            QQmlScript::Value *value = reference->value;
 +            const QString &expression = reference->rewrittenExpression;
 +
 +            if (ii != 0) functionArray.append(",", 1);
 +
 +            while (lineNumber < value->location.start.line) {
 +                lineNumber++;
 +                functionArray.append("\n", 1);
 +            }
 +
 +            functionArray += expression.toUtf8();
 +            lineNumber += expression.count(QLatin1Char('\n'));
 +            reference->compiledIndex = ii;
 +        }
 +        functionArray.append("]", 1);
 +
 +        compileState->v8BindingProgram = functionArray;
 +        compileState->v8BindingProgramLine = startLineNumber;
 +    }
 +
 +    if (bindingCompiler.isValid()) 
 +        compileState->compiledBindingData = bindingCompiler.program();
 +
 +    // Check pop()'s matched push()'s
 +    Q_ASSERT(compileState->objectDepth.depth() == 0);
 +    Q_ASSERT(compileState->listDepth.depth() == 0);
 +
 +    saveComponentState();
 +
 +    return true;
 +}
 +
 +void QQmlCompiler::dumpStats()
 +{
 +    Q_ASSERT(componentStats);
 +    qWarning().nospace() << "QML Document: " << output->url.toString();
 +    for (int ii = 0; ii < componentStats->savedComponentStats.count(); ++ii) {
 +        const ComponentStat &stat = componentStats->savedComponentStats.at(ii);
 +        qWarning().nospace() << "    Component Line " << stat.lineNumber;
 +        qWarning().nospace() << "        Total Objects:      " << stat.objects;
 +        qWarning().nospace() << "        IDs Used:           " << stat.ids;
 +        qWarning().nospace() << "        Optimized Bindings: " << stat.optimizedBindings.count();
 +
 +        {
 +        QByteArray output;
 +        for (int ii = 0; ii < stat.optimizedBindings.count(); ++ii) {
 +            if (0 == (ii % 10)) {
 +                if (ii) output.append("\n");
 +                output.append("            ");
 +            }
 +
 +            output.append("(");
 +            output.append(QByteArray::number(stat.optimizedBindings.at(ii).start.line));
 +            output.append(":");
 +            output.append(QByteArray::number(stat.optimizedBindings.at(ii).start.column));
 +            output.append(") ");
 +        }
 +        if (!output.isEmpty())
 +            qWarning().nospace() << output.constData();
 +        }
 +
++        qWarning().nospace() << "        Shared Bindings:    " << stat.sharedBindings.count();
++        {
++        QByteArray output;
++        for (int ii = 0; ii < stat.sharedBindings.count(); ++ii) {
++            if (0 == (ii % 10)) {
++                if (ii) output.append("\n");
++                output.append("            ");
++            }
++
++            output.append("(");
++            output.append(QByteArray::number(stat.sharedBindings.at(ii).start.line));
++            output.append(":");
++            output.append(QByteArray::number(stat.sharedBindings.at(ii).start.column));
++            output.append(") ");
++        }
++        if (!output.isEmpty())
++            qWarning().nospace() << output.constData();
++        }
++
 +        qWarning().nospace() << "        QScript Bindings:   " << stat.scriptBindings.count();
 +        {
 +        QByteArray output;
 +        for (int ii = 0; ii < stat.scriptBindings.count(); ++ii) {
 +            if (0 == (ii % 10)) {
 +                if (ii) output.append("\n");
 +                output.append("            ");
 +            }
 +
 +            output.append("(");
 +            output.append(QByteArray::number(stat.scriptBindings.at(ii).start.line));
 +            output.append(":");
 +            output.append(QByteArray::number(stat.scriptBindings.at(ii).start.column));
 +            output.append(") ");
 +        }
 +        if (!output.isEmpty())
 +            qWarning().nospace() << output.constData();
 +        }
 +    }
 +}
 +
 +/*!
 +    Returns true if from can be assigned to a (QObject) property of type
 +    to.
 +*/
 +bool QQmlCompiler::canCoerce(int to, QQmlScript::Object *from)
 +{
 +    const QMetaObject *toMo = enginePrivate->rawMetaObjectForType(to);
 +    const QMetaObject *fromMo = from->metaObject();
 +
 +    while (fromMo) {
 +        if (QQmlPropertyPrivate::equal(fromMo, toMo))
 +            return true;
 +        fromMo = fromMo->superClass();
 +    }
 +    return false;
 +}
 +
 +/*!
 +    Returns the element name, as written in the QML file, for o.
 +*/
 +QString QQmlCompiler::elementName(QQmlScript::Object *o)
 +{
 +    Q_ASSERT(o);
 +    if (o->type != -1) {
 +        return output->types.at(o->type).className;
 +    } else {
 +        return QString();
 +    }
 +}
 +
 +QQmlType *QQmlCompiler::toQmlType(QQmlScript::Object *from)
 +{
 +    // ### Optimize
 +    const QMetaObject *mo = from->metatype;
 +    QQmlType *type = 0;
 +    while (!type && mo) {
 +        type = QQmlMetaType::qmlType(mo);
 +        mo = mo->superClass();
 +    }
 +   return type;
 +}
 +
 +QStringList QQmlCompiler::deferredProperties(QQmlScript::Object *obj)
 +{
 +    const QMetaObject *mo = obj->metatype;
 +
 +    int idx = mo->indexOfClassInfo("DeferredPropertyNames");
 +    if (idx == -1)
 +        return QStringList();
 +
 +    QMetaClassInfo classInfo = mo->classInfo(idx);
 +    QStringList rv = QString::fromUtf8(classInfo.value()).split(QLatin1Char(','));
 +    return rv;
 +}
 +
 +QQmlPropertyData *
 +QQmlCompiler::property(QQmlScript::Object *object, int index)
 +{
 +    QQmlPropertyCache *cache = 0;
 +
 +    if (object->synthCache)
 +        cache = object->synthCache;
 +    else if (object->type != -1)
 +        cache = output->types[object->type].createPropertyCache(engine);
 +    else
 +        cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject());
 +
 +    return cache->property(index);
 +}
 +
 +QQmlPropertyData *
 +QQmlCompiler::property(QQmlScript::Object *object, const QHashedStringRef &name, bool *notInRevision)
 +{
 +    if (notInRevision) *notInRevision = false;
 +
 +    QQmlPropertyCache *cache = 0;
 +
 +    if (object->synthCache)
 +        cache = object->synthCache;
 +    else if (object->type != -1)
 +        cache = output->types[object->type].createPropertyCache(engine);
 +    else
 +        cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject());
 +
 +    QQmlPropertyData *d = cache->property(name);
 +
 +    // Find the first property
 +    while (d && d->isFunction())
 +        d = cache->overrideData(d);
 +
 +    if (d && !cache->isAllowedInRevision(d)) {
 +        if (notInRevision) *notInRevision = true;
 +        return 0;
 +    } else {
 +        return d;
 +    }
 +}
 +
 +// This code must match the semantics of QQmlPropertyPrivate::findSignalByName
 +QQmlPropertyData *
 +QQmlCompiler::signal(QQmlScript::Object *object, const QHashedStringRef &name, bool *notInRevision)
 +{
 +    if (notInRevision) *notInRevision = false;
 +
 +    QQmlPropertyCache *cache = 0;
 +
 +    if (object->synthCache)
 +        cache = object->synthCache;
 +    else if (object->type != -1)
 +        cache = output->types[object->type].createPropertyCache(engine);
 +    else
 +        cache = QQmlEnginePrivate::get(engine)->cache(object->metaObject());
 +
 +
 +    QQmlPropertyData *d = cache->property(name);
 +    if (notInRevision) *notInRevision = false;
 +
 +    while (d && !(d->isFunction()))
 +        d = cache->overrideData(d);
 +
 +    if (d && !cache->isAllowedInRevision(d)) {
 +        if (notInRevision) *notInRevision = true;
 +        return 0;
 +    } else if (d) {
 +        return d;
 +    }
 +
 +    if (name.endsWith(Changed_string)) {
 +        QHashedStringRef propName = name.mid(0, name.length() - Changed_string.length());
 +
 +        d = property(object, propName, notInRevision);
 +        if (d) 
 +            return cache->method(d->notifyIndex);
 +    }
 +
 +    return 0;
 +}
 +
 +// This code must match the semantics of QQmlPropertyPrivate::findSignalByName
 +int QQmlCompiler::indexOfSignal(QQmlScript::Object *object, const QString &name, 
 +                                        bool *notInRevision)
 +{
 +    QQmlPropertyData *d = signal(object, QStringRef(&name), notInRevision);
 +    return d?d->coreIndex:-1;
 +}
 +
 +int QQmlCompiler::indexOfProperty(QQmlScript::Object *object, const QString &name, 
 +                                          bool *notInRevision)
 +{
 +    return indexOfProperty(object, QStringRef(&name), notInRevision);
 +}
 +
 +int QQmlCompiler::indexOfProperty(QQmlScript::Object *object, const QHashedStringRef &name, 
 +                                          bool *notInRevision)
 +{
 +    QQmlPropertyData *d = property(object, name, notInRevision);
 +    return d?d->coreIndex:-1;
 +}
 +
 +QT_END_NAMESPACE
index 9b13b7e,0000000..3b6fdf1
mode 100644,000000..100644
--- /dev/null
@@@ -1,466 -1,0 +1,467 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLCOMPILER_P_H
 +#define QQMLCOMPILER_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 "qqml.h"
 +#include "qqmlerror.h"
 +#include <private/qv8_p.h>
 +#include "qqmlinstruction_p.h"
 +#include "qqmlscript_p.h"
 +#include "qqmlengine_p.h"
 +#include <private/qbitfield_p.h>
 +#include "qqmlpropertycache_p.h"
 +#include "qqmlintegercache_p.h"
 +#include "qqmltypenamecache_p.h"
 +#include "qqmltypeloader_p.h"
 +
 +#include <QtCore/qbytearray.h>
 +#include <QtCore/qset.h>
 +#include <QtCore/QCoreApplication>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QQmlEngine;
 +class QQmlComponent;
 +class QQmlContext;
 +class QQmlContextData;
 +
 +class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount,
 +                                                   public QQmlCleanup
 +{
 +public:
 +    QQmlCompiledData(QQmlEngine *engine);
 +    virtual ~QQmlCompiledData();
 +
 +    QQmlEngine *engine;
 +
 +    QString name;
 +    QUrl url;
 +    QQmlTypeNameCache *importCache;
 +
 +    struct TypeReference 
 +    {
 +        TypeReference()
 +        : type(0), typePropertyCache(0), component(0) {}
 +
 +        QString className;
 +        QQmlType *type;
 +        QQmlPropertyCache *typePropertyCache;
 +        QQmlCompiledData *component;
 +
 +        const QMetaObject *metaObject() const;
 +        QQmlPropertyCache *propertyCache() const;
 +        QQmlPropertyCache *createPropertyCache(QQmlEngine *);
 +    };
 +    QList<TypeReference> types;
 +
 +    struct V8Program {
 +        V8Program(const QByteArray &p, QQmlCompiledData *c)
 +        : program(p), cdata(c) {}
 +
 +        QByteArray program;
 +        v8::Persistent<v8::Array> bindings;
 +        QQmlCompiledData *cdata;
 +    };
 +
 +    QList<V8Program> programs;
 +
 +    const QMetaObject *root;
 +    QAbstractDynamicMetaObject rootData;
 +    QQmlPropertyCache *rootPropertyCache;
 +    QList<QString> primitives;
 +    QList<QByteArray> datas;
 +    QByteArray bytecode;
 +    QList<QQmlPropertyCache *> propertyCaches;
 +    QList<QQmlIntegerCache *> contextCaches;
 +    QList<QQmlScriptData *> scripts;
 +    QList<QUrl> urls;
 +
 +    struct Instruction {
 +#define QML_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlInstructionData<QQmlInstruction::I> I;
 +    FOR_EACH_QML_INSTR(QML_INSTR_DATA_TYPEDEF)
 +#undef QML_INSTR_DATA_TYPEDEF
 +    private:
 +        Instruction();
 +    };
 +
 +    void dumpInstructions();
 +
 +    template <int Instr>
 +    int addInstruction(const QQmlInstructionData<Instr> &data)
 +    {
 +        QQmlInstruction genericInstr;
 +        QQmlInstructionMeta<Instr>::setData(genericInstr, data);
 +        return addInstructionHelper(static_cast<QQmlInstruction::Type>(Instr), genericInstr);
 +    }
 +    int nextInstructionIndex();
 +    QQmlInstruction *instruction(int index);
 +    QQmlInstruction::Type instructionType(const QQmlInstruction *instr);
 +
 +    bool isInitialized() const { return hasEngine(); }
 +    void initialize(QQmlEngine *);
 +
 +protected:
 +    virtual void destroy(); // From QQmlRefCount
 +    virtual void clear(); // From QQmlCleanup
 +
 +private:
 +    friend class QQmlCompiler;
 +
 +    int addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr);
 +    void dump(QQmlInstruction *, int idx = -1);
 +    QQmlCompiledData(const QQmlCompiledData &other);
 +    QQmlCompiledData &operator=(const QQmlCompiledData &other);
 +    QByteArray packData;
 +    int pack(const char *, size_t);
 +
 +    int indexForString(const QString &);
 +    int indexForByteArray(const QByteArray &);
 +    int indexForUrl(const QUrl &);
 +};
 +
 +namespace QQmlCompilerTypes {
 +    struct BindingContext 
 +    {
 +        BindingContext()
 +            : stack(0), owner(0), object(0) {}
 +        BindingContext(QQmlScript::Object *o)
 +            : stack(0), owner(0), object(o) {}
 +        BindingContext incr() const {
 +            BindingContext rv(object);
 +            rv.stack = stack + 1;
 +            return rv;
 +        }
 +        bool isSubContext() const { return stack != 0; }
 +        int stack;
 +        int owner;
 +        QQmlScript::Object *object;
 +    };
 +
 +    struct BindingReference
 +    {
 +        enum DataType { QtScript, V4, V8,
 +                        Tr, TrId };
 +        DataType dataType;
 +    };
 +
 +    struct JSBindingReference : public QQmlPool::Class,
 +                                public BindingReference
 +    {
 +        JSBindingReference() : nextReference(0) {}
 +
 +        QQmlScript::Variant expression;
 +        QQmlScript::Property *property;
 +        QQmlScript::Value *value;
 +
 +        int compiledIndex;
 +
 +        QString rewrittenExpression;
 +        BindingContext bindingContext;
 +
 +        JSBindingReference *nextReference;
 +    };
 +
 +    struct TrBindingReference : public QQmlPool::POD,
 +                                public BindingReference
 +    {
 +        QStringRef text;
 +        QStringRef comment;
 +        int n;
 +    };
 +
 +    struct IdList : public QFieldList<QQmlScript::Object, 
 +                                      &QQmlScript::Object::nextIdObject>
 +    {
 +        QQmlScript::Object *value(const QString &id) const {
 +            for (QQmlScript::Object *o = first(); o; o = next(o)) {
 +                if (o->id == id)
 +                    return o;
 +            }
 +            return 0;
 +        }
 +    };
 +
 +    struct DepthStack {
 +        DepthStack() : _depth(0), _maxDepth(0) {}
 +        DepthStack(const DepthStack &o) : _depth(o._depth), _maxDepth(o._maxDepth) {}
 +        DepthStack &operator=(const DepthStack &o) { _depth = o._depth; _maxDepth = o._maxDepth; return *this; }
 +
 +        int depth() const { return _depth; }
 +        int maxDepth() const { return _maxDepth; }
 +
 +        void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); }
 +        void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); }
 +
 +        void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); }
 +    private:
 +        int _depth;
 +        int _maxDepth;
 +    };
 +
 +    // Contains all the incremental compiler state about a component.  As
 +    // a single QML file can have multiple components defined, there may be
 +    // more than one of these for each compile
 +    struct ComponentCompileState : public QQmlPool::Class
 +    {
 +        ComponentCompileState() 
 +        : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false), 
 +          v8BindingProgramLine(-1), root(0) {}
 +
 +        IdList ids;
 +        int parserStatusCount;
 +        int totalBindingsCount;
 +        int pushedProperties;
 +        bool nested;
 +
 +        QByteArray compiledBindingData;
 +        QByteArray v8BindingProgram;
 +        int v8BindingProgramLine;
 +
 +        DepthStack objectDepth;
 +        DepthStack listDepth;
 +
 +        typedef QQmlCompilerTypes::JSBindingReference B;
 +        typedef QFieldList<B, &B::nextReference> JSBindingReferenceList;
 +        JSBindingReferenceList bindings;
 +        typedef QQmlScript::Object O;
 +        typedef QFieldList<O, &O::nextAliasingObject> AliasingObjectsList;
 +        AliasingObjectsList aliasingObjects;
 +        QQmlScript::Object *root;
 +    };
 +};
 +
 +class QMetaObjectBuilder;
 +class Q_AUTOTEST_EXPORT QQmlCompiler
 +{
 +    Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
 +public:
 +    QQmlCompiler(QQmlPool *);
 +
 +    bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *);
 +
 +    bool isError() const;
 +    QList<QQmlError> errors() const;
 +
 +    static bool isAttachedPropertyName(const QString &);
 +    static bool isSignalPropertyName(const QString &);
 +    static bool isAttachedPropertyName(const QHashedStringRef &);
 +    static bool isSignalPropertyName(const QHashedStringRef &);
 +
 +    int evaluateEnum(const QByteArray& script) const; // for QQmlCustomParser::evaluateEnum
 +    const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType
 +    int rewriteBinding(const QQmlScript::Variant& value, const QString& name); // for QQmlCustomParser::rewriteBinding
 +    QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name);  // for QQmlCustomParser::rewriteSignalHandler
 +
 +private:
 +    typedef QQmlCompiledData::Instruction Instruction;
 +
 +    static void reset(QQmlCompiledData *);
 +
 +    void compileTree(QQmlScript::Object *tree);
 +
 +
 +    bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
 +    bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
 +    bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
 +    bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj, 
 +                     const QQmlCompilerTypes::BindingContext &);
 +    bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, 
 +                       const QQmlCompilerTypes::BindingContext &);
 +    bool buildPropertyInNamespace(QQmlImportedNamespace *ns,
 +                                  QQmlScript::Property *prop, 
 +                                  QQmlScript::Object *obj, 
 +                                  const QQmlCompilerTypes::BindingContext &);
 +    bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
 +    bool buildAttachedProperty(QQmlScript::Property *prop, 
 +                               QQmlScript::Object *obj,
 +                               const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool buildGroupedProperty(QQmlScript::Property *prop,
 +                              QQmlScript::Object *obj,
 +                              const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool buildValueTypeProperty(QObject *type, 
 +                                QQmlScript::Object *obj, 
 +                                QQmlScript::Object *baseObj,
 +                                const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool buildListProperty(QQmlScript::Property *prop,
 +                           QQmlScript::Object *obj,
 +                           const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool buildScriptStringProperty(QQmlScript::Property *prop,
 +                                   QQmlScript::Object *obj,
 +                                   const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool buildPropertyAssignment(QQmlScript::Property *prop,
 +                                 QQmlScript::Object *obj,
 +                                 const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool buildPropertyObjectAssignment(QQmlScript::Property *prop,
 +                                       QQmlScript::Object *obj,
 +                                       QQmlScript::Value *value,
 +                                       const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool buildPropertyOnAssignment(QQmlScript::Property *prop,
 +                                   QQmlScript::Object *obj,
 +                                   QQmlScript::Object *baseObj,
 +                                   QQmlScript::Value *value,
 +                                   const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool buildPropertyLiteralAssignment(QQmlScript::Property *prop,
 +                                        QQmlScript::Object *obj,
 +                                        QQmlScript::Value *value,
 +                                        const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool doesPropertyExist(QQmlScript::Property *prop, QQmlScript::Object *obj);
 +    bool testLiteralAssignment(QQmlScript::Property *prop,
 +                               QQmlScript::Value *value);
 +    bool testQualifiedEnumAssignment(QQmlScript::Property *prop,
 +                                     QQmlScript::Object *obj,
 +                                     QQmlScript::Value *value,
 +                                     bool *isAssignment);
 +    enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation };
 +    bool mergeDynamicMetaProperties(QQmlScript::Object *obj);
 +    bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode);
 +    bool checkDynamicMeta(QQmlScript::Object *obj);
 +    bool buildBinding(QQmlScript::Value *, QQmlScript::Property *prop,
 +                      const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool buildLiteralBinding(QQmlScript::Value *, QQmlScript::Property *prop,
 +                             const QQmlCompilerTypes::BindingContext &ctxt);
 +    bool buildComponentFromRoot(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
 +    bool compileAlias(QFastMetaBuilder &, 
 +                      QByteArray &data,
 +                      QQmlScript::Object *obj, 
 +                      int propIndex, int aliasIndex,
 +                      QQmlScript::Object::DynamicProperty &);
 +    bool completeComponentBuild();
 +    bool checkValidId(QQmlScript::Value *, const QString &);
 +
 +
 +    void genObject(QQmlScript::Object *obj);
 +    void genObjectBody(QQmlScript::Object *obj);
 +    void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *);
 +    void genComponent(QQmlScript::Object *obj);
 +    void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
 +    void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
 +    void genPropertyAssignment(QQmlScript::Property *prop, 
 +                               QQmlScript::Object *obj,
 +                               QQmlScript::Property *valueTypeProperty = 0);
 +    void genLiteralAssignment(QQmlScript::Property *prop,
 +                              QQmlScript::Value *value);
 +    void genBindingAssignment(QQmlScript::Value *binding, 
 +                              QQmlScript::Property *prop, 
 +                              QQmlScript::Object *obj,
 +                              QQmlScript::Property *valueTypeProperty = 0);
 +    int genContextCache();
 +
 +    QQmlPropertyData genValueTypeData(QQmlScript::Property *prop,
 +                                              QQmlScript::Property *valueTypeProp);
 +
 +    int componentTypeRef();
 +    int translationContextIndex();
 +
 +    static QQmlType *toQmlType(QQmlScript::Object *from);
 +    bool canCoerce(int to, QQmlScript::Object *from);
 +
 +    QString elementName(QQmlScript::Object *);
 +
 +    QStringList deferredProperties(QQmlScript::Object *);
 +
 +    QQmlPropertyData *property(QQmlScript::Object *, int);
 +    QQmlPropertyData *property(QQmlScript::Object *, const QHashedStringRef &,
 +                                       bool *notInRevision = 0);
 +    QQmlPropertyData *signal(QQmlScript::Object *, const QHashedStringRef &,
 +                                     bool *notInRevision = 0);
 +    int indexOfProperty(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0);
 +    int indexOfProperty(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
 +    int indexOfSignal(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
 +
 +    void addId(const QString &, QQmlScript::Object *);
 +
 +    void dumpStats();
 +
 +    void addBindingReference(QQmlCompilerTypes::JSBindingReference *);
 +
 +    QQmlCompilerTypes::ComponentCompileState *compileState;
 +
 +    QQmlPool *pool;
 +
 +    QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *);
 +    void saveComponentState();
 +
 +    QList<QQmlError> exceptions;
 +    QQmlCompiledData *output;
 +    QQmlEngine *engine;
 +    QQmlEnginePrivate *enginePrivate;
 +    QQmlScript::Object *unitRoot;
 +    QQmlTypeData *unit;
 +    int cachedComponentTypeRef;
 +    int cachedTranslationContextIndex;
 +
 +    // Compiler component statistics.  Only collected if QML_COMPILER_STATS=1
 +    struct ComponentStat
 +    {
 +        ComponentStat() : ids(0), objects(0) {}
 +
 +        int lineNumber;
 +
 +        int ids;
 +        QList<QQmlScript::LocationSpan> scriptBindings;
++        QList<QQmlScript::LocationSpan> sharedBindings;
 +        QList<QQmlScript::LocationSpan> optimizedBindings;
 +        int objects;
 +    };
 +    struct ComponentStats : public QQmlPool::Class
 +    {
 +        ComponentStat componentStat;
 +        QList<ComponentStat> savedComponentStats;
 +    };
 +    ComponentStats *componentStats;
 +};
 +
 +QT_END_NAMESPACE
 +
 +#endif // QQMLCOMPILER_P_H
index e168f06,0000000..5dd8fc8
mode 100644,000000..100644
--- /dev/null
@@@ -1,1350 -1,0 +1,1352 @@@
-     bool isRoot = enginePriv->inProgressCreations == 0;
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlcomponent.h"
 +#include "qqmlcomponent_p.h"
 +#include "qqmlcomponentattached_p.h"
 +
 +#include "qqmlcompiler_p.h"
 +#include "qqmlcontext_p.h"
 +#include "qqmlengine_p.h"
 +#include "qqmlvme_p.h"
 +#include "qqml.h"
 +#include "qqmlengine.h"
 +#include "qqmlbinding_p.h"
 +#include "qqmlbinding_p_p.h"
++#include "qqmlglobal_p.h"
 +#include "qqmlscript_p.h"
 +#include <private/qqmlprofilerservice_p.h>
 +#include <private/qqmlenginedebugservice_p.h>
 +#include "qqmlincubator.h"
 +#include "qqmlincubator_p.h"
 +
 +#include <private/qv8engine_p.h>
 +#include <private/qv8include_p.h>
 +
 +#include <QStack>
 +#include <QStringList>
 +#include <QtCore/qdebug.h>
 +#include <qqmlinfo.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QQmlComponentExtension : public QV8Engine::Deletable
 +{
 +public:
 +    QQmlComponentExtension(QV8Engine *);
 +    virtual ~QQmlComponentExtension();
 +
 +    v8::Persistent<v8::Function> incubationConstructor;
 +    v8::Persistent<v8::Script> initialProperties;
 +    v8::Persistent<v8::Function> forceCompletion;
 +};
 +V8_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension);
 +
 +/*
 +    Try to do what's necessary for a reasonable display of the type
 +    name, but no more (just enough for the client to do more extensive cleanup).
 +
 +    Should only be called when debugging is enabled.
 +*/
 +static inline QString buildTypeNameForDebug(const QMetaObject *metaObject)
 +{
 +    static const QString qmlMarker(QLatin1String("_QML"));
 +    static const QChar underscore(QLatin1Char('_'));
 +    static const QChar asterisk(QLatin1Char('*'));
 +    QQmlType *type = QQmlMetaType::qmlType(metaObject);
 +    QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(metaObject->className());
 +    if (!type) {
 +        //### optimize further?
 +        int marker = typeName.indexOf(qmlMarker);
 +        if (marker != -1 && marker < typeName.count() - 1) {
 +            if (typeName[marker + 1] == underscore) {
 +                const QString className = typeName.left(marker) + asterisk;
 +                type = QQmlMetaType::qmlType(QMetaType::type(className.toUtf8()));
 +                if (type)
 +                    typeName = type->qmlTypeName();
 +            }
 +        }
 +    }
 +    return typeName;
 +}
 +
 +/*!
 +    \class QQmlComponent
 +    \since 4.7
 +    \brief The QQmlComponent class encapsulates a QML component definition.
 +    \mainclass
 +
 +    Components are reusable, encapsulated QML elements with well-defined interfaces.
 +    They are often defined in \l {qdeclarativedocuments.html}{Component Files}.
 +
 +    A QQmlComponent instance can be created from a QML file.
 +    For example, if there is a \c main.qml file like this:
 +
 +    \qml
 +    import QtQuick 2.0
 +
 +    Item {
 +        width: 200
 +        height: 200
 +    }
 +    \endqml
 +
 +    The following code loads this QML file as a component, creates an instance of
 +    this component using create(), and then queries the \l Item's \l {Item::}{width}
 +    value:
 +
 +    \code
 +    QQmlEngine *engine = new QQmlEngine;
 +    QQmlComponent component(engine, QUrl::fromLocalFile("main.qml"));
 +
 +    QObject *myObject = component.create();
 +    QQuickItem *item = qobject_cast<QQuickItem*>(myObject);
 +    int width = item->width();  // width = 200
 +    \endcode
 +
 +
 +    \section2 Network Components
 +
 +    If the URL passed to QQmlComponent is a network resource, or if the QML document references a
 +    network resource, the QQmlComponent has to fetch the network data before it is able to create
 +    objects.  In this case, the QQmlComponent will have a \l {QQmlComponent::Loading}{Loading}
 +    \l {QQmlComponent::status()}{status}.  An application will have to wait until the component
 +    is \l {QQmlComponent::Ready}{Ready} before calling \l {QQmlComponent::create()}.
 +
 +    The following example shows how to load a QML file from a network resource.  After creating
 +    the QQmlComponent, it tests whether the component is loading.  If it is, it connects to the
 +    QQmlComponent::statusChanged() signal and otherwise calls the \c {continueLoading()} method
 +    directly. Note that QQmlComponent::isLoading() may be false for a network component if the
 +    component has been cached and is ready immediately.
 +
 +    \code
 +    MyApplication::MyApplication()
 +    {
 +        // ...
 +        component = new QQmlComponent(engine, QUrl("http://www.example.com/main.qml"));
 +        if (component->isLoading())
 +            QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)),
 +                             this, SLOT(continueLoading()));
 +        else
 +            continueLoading();
 +    }
 +
 +    void MyApplication::continueLoading()
 +    {
 +        if (component->isError()) {
 +            qWarning() << component->errors();
 +        } else {
 +            QObject *myObject = component->create();
 +        }
 +    }
 +    \endcode
 +
 +    \sa {Using QML Bindings in C++ Applications}, {Integrating QML Code with Existing Qt UI Code}
 +*/
 +
 +/*!
 +    \qmlclass Component QQmlComponent
 +    \ingroup qml-utility-elements
 +    \since 4.7
 +    \brief The Component element encapsulates a QML component definition.
 +
 +    Components are reusable, encapsulated QML elements with well-defined interfaces.
 +
 +    Components are often defined by \l {qdeclarativedocuments.html}{component files} -
 +    that is, \c .qml files. The \e Component element essentially allows QML components
 +    to be defined inline, within a \l {QML Document}{QML document}, rather than as a separate QML file.
 +    This may be useful for reusing a small component within a QML file, or for defining
 +    a component that logically belongs with other QML components within a file.
 +
 +    For example, here is a component that is used by multiple \l Loader objects.
 +    It contains a single item, a \l Rectangle:
 +
 +    \snippet doc/src/snippets/qml/component.qml 0
 +
 +    Notice that while a \l Rectangle by itself would be automatically 
 +    rendered and displayed, this is not the case for the above rectangle
 +    because it is defined inside a \c Component. The component encapsulates the
 +    QML elements within, as if they were defined in a separate QML
 +    file, and is not loaded until requested (in this case, by the
 +    two \l Loader objects).
 +
 +    Defining a \c Component is similar to defining a \l {QML Document}{QML document}.
 +    A QML document has a single top-level item that defines the behaviors and
 +    properties of that component, and cannot define properties or behaviors outside
 +    of that top-level item. In the same way, a \c Component definition contains a single
 +    top level item (which in the above example is a \l Rectangle) and cannot define any
 +    data outside of this item, with the exception of an \e id (which in the above example
 +    is \e redSquare).
 +
 +    The \c Component element is commonly used to provide graphical components
 +    for views. For example, the ListView::delegate property requires a \c Component
 +    to specify how each list item is to be displayed.
 +
 +    \c Component objects can also be created dynamically using
 +    \l{QML:Qt::createComponent()}{Qt.createComponent()}.
 +*/
 +
 +/*!
 +    \qmlattachedsignal Component::onCompleted()
 +
 +    Emitted after component "startup" has completed.  This can be used to
 +    execute script code at startup, once the full QML environment has been
 +    established.
 +
 +    The \c {Component::onCompleted} attached property can be applied to
 +    any element.  The order of running the \c onCompleted scripts is
 +    undefined.
 +
 +    \qml
 +    Rectangle {
 +        Component.onCompleted: console.log("Completed Running!")
 +        Rectangle {
 +            Component.onCompleted: console.log("Nested Completed Running!")
 +        }
 +    }
 +    \endqml
 +*/
 +
 +/*!
 +    \qmlattachedsignal Component::onDestruction()
 +
 +    Emitted as the component begins destruction.  This can be used to undo
 +    work done in the onCompleted signal, or other imperative code in your
 +    application.
 +
 +    The \c {Component::onDestruction} attached property can be applied to
 +    any element.  However, it applies to the destruction of the component as
 +    a whole, and not the destruction of the specific object.  The order of
 +    running the \c onDestruction scripts is undefined.
 +
 +    \qml
 +    Rectangle {
 +        Component.onDestruction: console.log("Destruction Beginning!")
 +        Rectangle {
 +            Component.onDestruction: console.log("Nested Destruction Beginning!")
 +        }
 +    }
 +    \endqml
 +
 +    \sa QtQml
 +*/
 +
 +/*!
 +    \enum QQmlComponent::Status
 +    
 +    Specifies the loading status of the QQmlComponent.
 +
 +    \value Null This QQmlComponent has no data.  Call loadUrl() or setData() to add QML content.
 +    \value Ready This QQmlComponent is ready and create() may be called.
 +    \value Loading This QQmlComponent is loading network data.
 +    \value Error An error has occurred.  Call errors() to retrieve a list of \{QQmlError}{errors}.
 +*/
 +
 +void QQmlComponentPrivate::typeDataReady(QQmlTypeData *)
 +{
 +    Q_Q(QQmlComponent);
 +
 +    Q_ASSERT(typeData);
 +
 +    fromTypeData(typeData);
 +    typeData = 0;
 +
 +    emit q->statusChanged(q->status());
 +}
 +
 +void QQmlComponentPrivate::typeDataProgress(QQmlTypeData *, qreal p)
 +{
 +    Q_Q(QQmlComponent);
 +
 +    progress = p;
 +
 +    emit q->progressChanged(p);
 +}
 +
 +void QQmlComponentPrivate::fromTypeData(QQmlTypeData *data)
 +{
 +    url = data->finalUrl();
 +    QQmlCompiledData *c = data->compiledData();
 +
 +    if (!c) {
 +        Q_ASSERT(data->isError());
 +        state.errors = data->errors();
 +    } else {
 +        cc = c;
 +    }
 +
 +    data->release();
 +}
 +
 +void QQmlComponentPrivate::clear()
 +{
 +    if (typeData) {
 +        typeData->unregisterCallback(this);
 +        typeData->release();
 +        typeData = 0;
 +    }
 +        
 +    if (cc) { 
 +        cc->release();
 +        cc = 0;
 +    }
 +}
 +
 +/*!
 +    \internal
 +*/
 +QQmlComponent::QQmlComponent(QObject *parent)
 +    : QObject(*(new QQmlComponentPrivate), parent)
 +{
 +}
 +
 +/*!
 +    Destruct the QQmlComponent.
 +*/
 +QQmlComponent::~QQmlComponent()
 +{
 +    Q_D(QQmlComponent);
 +
 +    if (d->state.completePending) {
 +        qWarning("QQmlComponent: Component destroyed while completion pending");
 +        d->completeCreate();
 +    }
 +
 +    if (d->typeData) {
 +        d->typeData->unregisterCallback(d);
 +        d->typeData->release();
 +    }
 +    if (d->cc)
 +        d->cc->release();
 +}
 +
 +/*!
 +    \qmlproperty enumeration Component::status
 +    This property holds the status of component loading.  It can be one of:
 +    \list
 +    \o Component.Null - no data is available for the component
 +    \o Component.Ready - the component has been loaded, and can be used to create instances.
 +    \o Component.Loading - the component is currently being loaded
 +    \o Component.Error - an error occurred while loading the component.
 +               Calling errorString() will provide a human-readable description of any errors.
 +    \endlist
 + */
 +
 +/*!
 +    \property QQmlComponent::status
 +    The component's current \l{QQmlComponent::Status} {status}.
 + */
 +QQmlComponent::Status QQmlComponent::status() const
 +{
 +    Q_D(const QQmlComponent);
 +
 +    if (d->typeData)
 +        return Loading;
 +    else if (!d->state.errors.isEmpty())
 +        return Error;
 +    else if (d->engine && d->cc)
 +        return Ready;
 +    else
 +        return Null;
 +}
 +
 +/*!
 +    Returns true if status() == QQmlComponent::Null.
 +*/
 +bool QQmlComponent::isNull() const
 +{
 +    return status() == Null;
 +}
 +
 +/*!
 +    Returns true if status() == QQmlComponent::Ready.
 +*/
 +bool QQmlComponent::isReady() const
 +{
 +    return status() == Ready;
 +}
 +
 +/*!
 +    Returns true if status() == QQmlComponent::Error.
 +*/
 +bool QQmlComponent::isError() const
 +{
 +    return status() == Error;
 +}
 +
 +/*!
 +    Returns true if status() == QQmlComponent::Loading.
 +*/
 +bool QQmlComponent::isLoading() const
 +{
 +    return status() == Loading;
 +}
 +
 +/*!
 +    \qmlproperty real Component::progress
 +    The progress of loading the component, from 0.0 (nothing loaded)
 +    to 1.0 (finished).
 +*/
 +
 +/*!
 +    \property QQmlComponent::progress
 +    The progress of loading the component, from 0.0 (nothing loaded)
 +    to 1.0 (finished).
 +*/
 +qreal QQmlComponent::progress() const
 +{
 +    Q_D(const QQmlComponent);
 +    return d->progress;
 +}
 +
 +/*!
 +    \fn void QQmlComponent::progressChanged(qreal progress)
 +
 +    Emitted whenever the component's loading progress changes.  \a progress will be the
 +    current progress between 0.0 (nothing loaded) and 1.0 (finished).
 +*/
 +
 +/*!
 +    \fn void QQmlComponent::statusChanged(QQmlComponent::Status status)
 +
 +    Emitted whenever the component's status changes.  \a status will be the
 +    new status.
 +*/
 +
 +/*!
 +    Create a QQmlComponent with no data and give it the specified
 +    \a engine and \a parent. Set the data with setData().
 +*/
 +QQmlComponent::QQmlComponent(QQmlEngine *engine, QObject *parent)
 +    : QObject(*(new QQmlComponentPrivate), parent)
 +{
 +    Q_D(QQmlComponent);
 +    d->engine = engine;
 +}
 +
 +/*!
 +    Create a QQmlComponent from the given \a url and give it the
 +    specified \a parent and \a engine.
 +
 +    Ensure that the URL provided is full and correct, in particular, use
 +    \l QUrl::fromLocalFile() when loading a file from the local filesystem.
 +
 +    \sa loadUrl()
 +*/
 +QQmlComponent::QQmlComponent(QQmlEngine *engine, const QUrl &url, QObject *parent)
 +: QObject(*(new QQmlComponentPrivate), parent)
 +{
 +    Q_D(QQmlComponent);
 +    d->engine = engine;
 +    loadUrl(url);
 +}
 +
 +/*!
 +    Create a QQmlComponent from the given \a fileName and give it the specified 
 +    \a parent and \a engine.
 +
 +    \sa loadUrl()
 +*/
 +QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName, 
 +                           QObject *parent)
 +: QObject(*(new QQmlComponentPrivate), parent)
 +{
 +    Q_D(QQmlComponent);
 +    d->engine = engine;
 +    loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName)));
 +}
 +
 +/*!
 +    \internal
 +*/
 +QQmlComponent::QQmlComponent(QQmlEngine *engine, QQmlCompiledData *cc, int start, QObject *parent)
 +    : QObject(*(new QQmlComponentPrivate), parent)
 +{
 +    Q_D(QQmlComponent);
 +    d->engine = engine;
 +    d->cc = cc;
 +    cc->addref();
 +    d->start = start;
 +    d->url = cc->url;
 +    d->progress = 1.0;
 +}
 +
 +/*!
 +    Sets the QQmlComponent 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 QQmlComponent::setData(const QByteArray &data, const QUrl &url)
 +{
 +    Q_D(QQmlComponent);
 +
 +    d->clear();
 +
 +    d->url = url;
 +
 +    QQmlTypeData *typeData = QQmlEnginePrivate::get(d->engine)->typeLoader.get(data, url);
 +    
 +    if (typeData->isCompleteOrError()) {
 +        d->fromTypeData(typeData);
 +    } else {
 +        d->typeData = typeData;
 +        d->typeData->registerCallback(d);
 +    }
 +
 +    d->progress = 1.0;
 +    emit statusChanged(status());
 +    emit progressChanged(d->progress);
 +}
 +
 +/*!
 +Returns the QQmlContext the component was created in.  This is only
 +valid for components created directly from QML.
 +*/
 +QQmlContext *QQmlComponent::creationContext() const
 +{
 +    Q_D(const QQmlComponent);
 +    if(d->creationContext)
 +        return d->creationContext->asQQmlContext();
 +
 +    return qmlContext(this);
 +}
 +
 +/*!
 +    Load the QQmlComponent from the provided \a url.
 +
 +    Ensure that the URL provided is full and correct, in particular, use
 +    \l QUrl::fromLocalFile() when loading a file from the local filesystem.
 +*/
 +void QQmlComponent::loadUrl(const QUrl &url)
 +{
 +    Q_D(QQmlComponent);
 +
 +    d->clear();
 +
 +    if ((url.isRelative() && !url.isEmpty())
 +    || url.scheme() == QLatin1String("file")) // Workaround QTBUG-11929
 +        d->url = d->engine->baseUrl().resolved(url);
 +    else
 +        d->url = url;
 +
 +    if (url.isEmpty()) {
 +        QQmlError error;
 +        error.setDescription(tr("Invalid empty URL"));
 +        d->state.errors << error;
 +        return;
 +    }
 +
 +    QQmlTypeData *data = QQmlEnginePrivate::get(d->engine)->typeLoader.get(d->url);
 +
 +    if (data->isCompleteOrError()) {
 +        d->fromTypeData(data);
 +        d->progress = 1.0;
 +    } else {
 +        d->typeData = data;
 +        d->typeData->registerCallback(d);
 +        d->progress = data->progress();
 +    }
 +
 +    emit statusChanged(status());
 +    emit progressChanged(d->progress);
 +}
 +
 +/*!
 +    Return the list of errors that occurred during the last compile or create
 +    operation.  An empty list is returned if isError() is not set.
 +*/
 +QList<QQmlError> QQmlComponent::errors() const
 +{
 +    Q_D(const QQmlComponent);
 +    if (isError())
 +        return d->state.errors;
 +    else
 +        return QList<QQmlError>();
 +}
 +
 +/*!
 +    \qmlmethod string Component::errorString()
 +
 +    Returns a human-readable description of any errors.
 +
 +    The string includes the file, location, and description of each error.
 +    If multiple errors are present they are separated by a newline character.
 +
 +    If no errors are present, an empty string is returned.
 +*/
 +
 +/*!
 +    \internal
 +    errorString is only meant as a way to get the errors in script
 +*/
 +QString QQmlComponent::errorString() const
 +{
 +    Q_D(const QQmlComponent);
 +    QString ret;
 +    if(!isError())
 +        return ret;
 +    foreach(const QQmlError &e, d->state.errors) {
 +        ret += e.url().toString() + QLatin1Char(':') +
 +               QString::number(e.line()) + QLatin1Char(' ') +
 +               e.description() + QLatin1Char('\n');
 +    }
 +    return ret;
 +}
 +
 +/*!
 +    \qmlproperty url Component::url
 +    The component URL.  This is the URL that was used to construct the component.
 +*/
 +
 +/*!
 +    \property QQmlComponent::url
 +    The component URL.  This is the URL passed to either the constructor,
 +    or the loadUrl() or setData() methods.
 +*/
 +QUrl QQmlComponent::url() const
 +{
 +    Q_D(const QQmlComponent);
 +    return d->url;
 +}
 +
 +/*!
 +    \internal
 +*/
 +QQmlComponent::QQmlComponent(QQmlComponentPrivate &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 {QQmlEngine::rootContext()}{root context}.
 +*/
 +QObject *QQmlComponent::create(QQmlContext *context)
 +{
 +    Q_D(QQmlComponent);
 +
 +    if (!context)
 +        context = d->engine->rootContext();
 +
 +    QObject *rv = beginCreate(context);
 +    completeCreate();
 +    return rv;
 +}
 +
 +/*!
 +    This method provides more advanced control over component instance creation.
 +    In general, programmers should use QQmlComponent::create() to create a 
 +    component.
 +
 +    Create an object instance from this component.  Returns 0 if creation
 +    failed.  \a publicContext specifies the context within which to create the object
 +    instance.  
 +
 +    When QQmlComponent 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, QQmlParserStatus::componentComplete() is called on objects.
 +    \endlist 
 +    QQmlComponent::beginCreate() differs from QQmlComponent::create() in that it
 +    only performs step 1.  QQmlComponent::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 *QQmlComponent::beginCreate(QQmlContext *publicContext)
 +{
 +    Q_D(QQmlComponent);
 +
 +    Q_ASSERT(publicContext);
 +    QQmlContextData *context = QQmlContextData::get(publicContext);
 +
 +    return d->beginCreate(context);
 +}
 +
 +QObject *
 +QQmlComponentPrivate::beginCreate(QQmlContextData *context)
 +{
 +    Q_Q(QQmlComponent);
 +    if (!context) {
 +        qWarning("QQmlComponent: Cannot create a component in a null context");
 +        return 0;
 +    }
 +
 +    if (!context->isValid()) {
 +        qWarning("QQmlComponent: Cannot create a component in an invalid context");
 +        return 0;
 +    }
 +
 +    if (context->engine != engine) {
 +        qWarning("QQmlComponent: Must create component in context from the same QQmlEngine");
 +        return 0;
 +    }
 +
 +    if (state.completePending) {
 +        qWarning("QQmlComponent: Cannot create new component instance before completing the previous");
 +        return 0;
 +    }
 +
 +    if (!q->isReady()) {
 +        qWarning("QQmlComponent: Component is not ready");
 +        return 0;
 +    }
 +
 +    QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
 +
-     if (isRoot) 
-         QQmlProfilerService::startRange(QQmlProfilerService::Creating);
++    if (enginePriv->inProgressCreations == 0) {
++        // only track root, since further ones might not be properly nested
++        profiler = new QQmlObjectCreatingProfiler();
++    }
++
 +    enginePriv->inProgressCreations++;
 +    state.errors.clear();
 +    state.completePending = true;
 +
-         if (isRoot) {
-             QQmlProfilerService::rangeData(QQmlProfilerService::Creating,
-                                               buildTypeNameForDebug(rv->metaObject()));
 +    enginePriv->referenceScarceResources();
 +    state.vme.init(context, cc, start, creationContext);
 +    QObject *rv = state.vme.execute(&state.errors);
 +    enginePriv->dereferenceScarceResources();
 +
 +    if (rv) {
 +        QQmlData *ddata = QQmlData::get(rv);
 +        Q_ASSERT(ddata);
 +        ddata->indestructible = true;
 +    }
 +
 +    if (enginePriv->isDebugging && rv) {
 +        if (!context->isInternal)
 +            context->asQQmlContextPrivate()->instances.append(rv);
 +        QQmlEngineDebugService::instance()->objectCreated(engine, rv);
-             QQmlProfilerService::rangeLocation(QQmlProfilerService::Creating,
-                                                   cc->url, data->lineNumber, data->columnNumber);
++
++        if (profiler && profiler->enabled) {
++            profiler->setTypeName(buildTypeNameForDebug(rv->metaObject()));
 +            QQmlData *data = QQmlData::get(rv);
 +            Q_ASSERT(data);
-         QQmlProfilerService::endRange(QQmlProfilerService::Creating);
++            profiler->setLocation(cc->url, data->lineNumber, data->columnNumber);
 +        }
 +    }
 +
 +    return rv;
 +}
 +
 +void QQmlComponentPrivate::beginDeferred(QQmlEnginePrivate *enginePriv,
 +                                                 QObject *object, ConstructionState *state)
 +{
 +    enginePriv->inProgressCreations++;
 +    state->errors.clear();
 +    state->completePending = true;
 +
 +    state->vme.initDeferred(object);
 +    state->vme.execute(&state->errors);
 +}
 +
 +void QQmlComponentPrivate::complete(QQmlEnginePrivate *enginePriv, ConstructionState *state)
 +{
 +    if (state->completePending) {
 +        state->vme.complete();
 +
 +        state->completePending = false;
 +
 +        enginePriv->inProgressCreations--;
 +
 +        if (0 == enginePriv->inProgressCreations) {
 +            while (enginePriv->erroredBindings) {
 +                enginePriv->warning(enginePriv->erroredBindings->error);
 +                enginePriv->erroredBindings->removeError();
 +            }
 +        }
 +    }
 +}
 +
 +/*!
 +    This method provides more advanced control over component instance creation.
 +    In general, programmers should use QQmlComponent::create() to create a 
 +    component.
 +
 +    Complete a component creation begin with QQmlComponent::beginCreate().
 +*/
 +void QQmlComponent::completeCreate()
 +{
 +    Q_D(QQmlComponent);
 +
 +    d->completeCreate();
 +}
 +
 +void QQmlComponentPrivate::completeCreate()
 +{
 +    if (state.completePending) {
 +        QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
 +        complete(ep, &state);
 +
++        delete profiler;
++        profiler = 0;
 +    }
 +}
 +
 +QQmlComponentAttached::QQmlComponentAttached(QObject *parent)
 +: QObject(parent), prev(0), next(0)
 +{
 +}
 +
 +QQmlComponentAttached::~QQmlComponentAttached()
 +{
 +    if (prev) *prev = next;
 +    if (next) next->prev = prev;
 +    prev = 0;
 +    next = 0;
 +}
 +
 +/*!
 +    \internal
 +*/
 +QQmlComponentAttached *QQmlComponent::qmlAttachedProperties(QObject *obj)
 +{
 +    QQmlComponentAttached *a = new QQmlComponentAttached(obj);
 +
 +    QQmlEngine *engine = qmlEngine(obj);
 +    if (!engine)
 +        return a;
 +
 +    if (QQmlEnginePrivate::get(engine)->activeVME) { // XXX should only be allowed during begin
 +        QQmlEnginePrivate *p = QQmlEnginePrivate::get(engine);
 +        a->add(&p->activeVME->componentAttached);
 +    } else {
 +        QQmlData *d = QQmlData::get(obj);
 +        Q_ASSERT(d);
 +        Q_ASSERT(d->context);
 +        a->add(&d->context->componentAttached);
 +    }
 +
 +    return a;
 +}
 +
 +void QQmlComponent::create(QQmlIncubator &i, QQmlContext *context,
 +                                   QQmlContext *forContext)
 +{
 +    Q_D(QQmlComponent);
 +
 +    if (!context) 
 +        context = d->engine->rootContext();
 +
 +    QQmlContextData *contextData = QQmlContextData::get(context);
 +    QQmlContextData *forContextData = contextData;
 +    if (forContext) forContextData = QQmlContextData::get(forContext);
 +
 +    if (!contextData->isValid()) {
 +        qWarning("QQmlComponent: Cannot create a component in an invalid context");
 +        return;
 +    }
 +
 +    if (contextData->engine != d->engine) {
 +        qWarning("QQmlComponent: Must create component in context from the same QQmlEngine");
 +        return;
 +    }
 +
 +    if (!isReady()) {
 +        qWarning("QQmlComponent: Component is not ready");
 +        return;
 +    }
 +
 +    i.clear();
 +    QQmlIncubatorPrivate *p = i.d;
 +
 +    QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(d->engine);
 +
 +    p->component = d->cc; p->component->addref();
 +    p->vme.init(contextData, d->cc, d->start, d->creationContext);
 +
 +    enginePriv->incubate(i, forContextData);
 +}
 +
 +class QV8IncubatorResource : public QV8ObjectResource,
 +                             public QQmlIncubator
 +{
 +V8_RESOURCE_TYPE(IncubatorType)
 +public:
 +    QV8IncubatorResource(QV8Engine *engine, IncubationMode = Asynchronous);
 +
 +    static v8::Handle<v8::Value> StatusChangedGetter(v8::Local<v8::String>, 
 +                                                     const v8::AccessorInfo& info);
 +    static v8::Handle<v8::Value> StatusGetter(v8::Local<v8::String>, 
 +                                              const v8::AccessorInfo& info);
 +    static v8::Handle<v8::Value> ObjectGetter(v8::Local<v8::String>, 
 +                                              const v8::AccessorInfo& info);
 +    static v8::Handle<v8::Value> ForceCompletionGetter(v8::Local<v8::String>, 
 +                                                       const v8::AccessorInfo& info);
 +    static v8::Handle<v8::Value> ForceCompletion(const v8::Arguments &args);
 +
 +    static void StatusChangedSetter(v8::Local<v8::String>, v8::Local<v8::Value> value, 
 +                                    const v8::AccessorInfo& info);
 +
 +    void dispose();
 +
 +    v8::Persistent<v8::Object> me;
 +    QQmlGuard<QObject> parent;
 +    v8::Persistent<v8::Value> valuemap;
 +    v8::Persistent<v8::Object> qmlGlobal;
 +protected:
 +    virtual void statusChanged(Status);
 +    virtual void setInitialState(QObject *);
 +};
 +
 +static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
 +{
 +    if (parent) {
 +        me->setParent(parent);
 +        typedef QQmlPrivate::AutoParentFunction APF;
 +        QList<APF> functions = QQmlMetaType::parentFunctions();
 +
 +        bool needParent = false;
 +        for (int ii = 0; ii < functions.count(); ++ii) {
 +            QQmlPrivate::AutoParentResult res = functions.at(ii)(me, parent);
 +            if (res == QQmlPrivate::Parented) {
 +                needParent = false;
 +                break;
 +            } else if (res == QQmlPrivate::IncompatibleParent) {
 +                needParent = true;
 +            }
 +        }
 +        if (needParent) 
 +            qWarning("QQmlComponent: Created graphical object was not "
 +                     "placed in the graphics scene.");
 +    }
 +}
 +
 +/*!
 +    \qmlmethod object Component::createObject(Item parent, object properties)
 +
 +    Creates and returns an object instance of this component that will have
 +    the given \a parent and \a properties. The \a properties argument is optional.
 +    Returns null if object creation fails.
 +
 +    The object will be created in the same context as the one in which the component
 +    was created. This function will always return null when called on components
 +    which were not created in QML.
 +
 +    If you wish to create an object without setting a parent, specify \c null for
 +    the \a parent value. Note that if the returned object is to be displayed, you 
 +    must provide a valid \a parent value or set the returned object's \l{Item::parent}{parent} 
 +    property, or else the object will not be visible.
 +
 +    If a \a parent is not provided to createObject(), a reference to the returned object must be held so that
 +    it is not destroyed by the garbage collector.  This is true regardless of whether \l{Item::parent} is set afterwards,
 +    since setting the Item parent does not change object ownership; only the graphical parent is changed.
 +
 +    As of QtQuick 1.1, this method accepts an optional \a properties argument that specifies a
 +    map of initial property values for the created object. These values are applied before object
 +    creation is finalized. (This is more efficient than setting property values after object creation,
 +    particularly where large sets of property values are defined, and also allows property bindings
 +    to be set up before the object is created.)
 +
 +    The \a properties argument is specified as a map of property-value items. For example, the code
 +    below creates an object with initial \c x and \c y values of 100 and 200, respectively:
 +
 +    \js
 +        var component = Qt.createComponent("Button.qml");
 +        if (component.status == Component.Ready)
 +            component.createObject(parent, {"x": 100, "y": 100});
 +    \endjs
 +
 +    Dynamically created instances can be deleted with the \c destroy() method.
 +    See \l {Dynamic Object Management in QML} for more information.
 +*/
 +void QQmlComponent::createObject(QQmlV8Function *args)
 +{
 +    Q_D(QQmlComponent);
 +    Q_ASSERT(d->engine);
 +    Q_ASSERT(args);
 +
 +    QObject *parent = 0;
 +    v8::Local<v8::Object> valuemap;
 +
 +    if (args->Length() >= 1) 
 +        parent = args->engine()->toQObject((*args)[0]);
 +
 +    if (args->Length() >= 2) {
 +        v8::Local<v8::Value> v = (*args)[1];
 +        if (!v->IsObject() || v->IsArray()) {
 +            qmlInfo(this) << tr("createObject: value is not an object");
 +            args->returnValue(v8::Null());
 +            return;
 +        }
 +        valuemap = v8::Local<v8::Object>::Cast(v);
 +    }
 +
 +    QV8Engine *v8engine = args->engine();
 +
 +    QQmlContext *ctxt = creationContext();
 +    if (!ctxt) ctxt = d->engine->rootContext();
 +
 +    QObject *rv = beginCreate(ctxt);
 +
 +    if (!rv) {
 +        args->returnValue(v8::Null());
 +        return;
 +    }
 +
 +    QQmlComponent_setQmlParent(rv, parent);
 +
 +    v8::Handle<v8::Value> ov = v8engine->newQObject(rv);
 +    Q_ASSERT(ov->IsObject());
 +    v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(ov);
 +
 +    if (!valuemap.IsEmpty()) {
 +        QQmlComponentExtension *e = componentExtension(v8engine);
 +        // Try catch isn't needed as the function itself is loaded with try/catch
 +        v8::Handle<v8::Value> function = e->initialProperties->Run(args->qmlGlobal());
 +        v8::Handle<v8::Value> args[] = { object, valuemap };
 +        v8::Handle<v8::Function>::Cast(function)->Call(v8engine->global(), 2, args);
 +    }
 +
 +    d->completeCreate();
 +
 +    Q_ASSERT(QQmlData::get(rv));
 +    QQmlData::get(rv)->setImplicitDestructible();
 +
 +    if (!rv)
 +        args->returnValue(v8::Null());
 +    else
 +        args->returnValue(object);
 +}
 +
 +/*!
 +    \qmlmethod object Component::incubateObject(Item parent, object properties, enum mode)
 +
 +    Creates an incubator for instance of this component.  Incubators allow new component 
 +    instances to be instantiated asynchronously and not cause freezes in the UI.
 +
 +    The \a parent argument specifies the parent the created instance will have.  Omitting the 
 +    parameter or passing null will create anobject with no parent.  In this case, a reference
 +    to the created object must be maintained by the application of the object will eventually
 +    be garbage collected.
 +
 +    The \a properties argument is specified as a map of property-value items which will be
 +    set on the created object during its construction.  \a mode may be Qt.Synchronous or 
 +    Qt.Asynchronous and controls whether the instance is created synchronously or asynchronously. 
 +    The default is asynchronously.  In some circumstances, even if Qt.Synchronous is specified,
 +    the incubator may create the object asynchronously.  This happens if the component calling
 +    incubateObject() is itself being created asynchronously.
 +
 +    All three arguments are optional.
 +
 +    If successful, the method returns an incubator, otherwise null.  The incubator has the following
 +    properties:
 +
 +    \list
 +    \i status The status of the incubator.  Valid values are Component.Ready, Component.Loading and
 +       Component.Error.
 +    \i object The created object instance.  Will only be available once the incubator is in the 
 +       Ready status.
 +    \i onStatusChanged Specifies a callback function to be invoked when the status changes.  The
 +       status is passed as a parameter to the callback.
 +    \i forceCompletion() Call to complete incubation synchronously.
 +    \endlist
 +
 +    The following example demonstrates how to use an incubator:
 +
 +    \js
 +        var component = Qt.createComponent("Button.qml");
 +
 +        var incubator = component.incubateObject(parent, { x: 10, y: 10 });
 +        if (incubator.status != Component.Ready) {
 +            incubator.onStatusChanged = function(status) {
 +                if (status == Component.Ready) {
 +                    print ("Object", incubator.object, "is now ready!");
 +                }
 +            }
 +        } else {
 +            print ("Object", incubator.object, "is ready immediately!");
 +        }
 +    \endjs
 +*/
 +
 +void QQmlComponent::incubateObject(QQmlV8Function *args)
 +{
 +    Q_D(QQmlComponent);
 +    Q_ASSERT(d->engine);
 +    Q_UNUSED(d);
 +    Q_ASSERT(args);
 +
 +    QObject *parent = 0;
 +    v8::Local<v8::Object> valuemap;
 +    QQmlIncubator::IncubationMode mode = QQmlIncubator::Asynchronous;
 +
 +    if (args->Length() >= 1) 
 +        parent = args->engine()->toQObject((*args)[0]);
 +
 +    if (args->Length() >= 2) {
 +        v8::Local<v8::Value> v = (*args)[1];
 +        if (v->IsNull()) {
 +        } else if (!v->IsObject() || v->IsArray()) {
 +            qmlInfo(this) << tr("createObject: value is not an object");
 +            args->returnValue(v8::Null());
 +            return;
 +        } else {
 +            valuemap = v8::Local<v8::Object>::Cast(v);
 +        }
 +    }
 +
 +    if (args->Length() >= 3) {
 +        quint32 v = (*args)[2]->Uint32Value();
 +        if (v == 0)
 +            mode = QQmlIncubator::Asynchronous;
 +        else if (v == 1)
 +            mode = QQmlIncubator::AsynchronousIfNested;
 +    }
 +
 +    QQmlComponentExtension *e = componentExtension(args->engine());
 +    
 +    QV8IncubatorResource *r = new QV8IncubatorResource(args->engine(), mode);
 +    v8::Local<v8::Object> o = e->incubationConstructor->NewInstance();
 +    o->SetExternalResource(r);
 +
 +    if (!valuemap.IsEmpty()) {
 +        r->valuemap = qPersistentNew(valuemap);
 +        r->qmlGlobal = qPersistentNew(args->qmlGlobal());
 +    }
 +    r->parent = parent;
 +    r->me = qPersistentNew(o);
 +
 +    create(*r, creationContext());
 +
 +    if (r->status() == QQmlIncubator::Null) {
 +        r->dispose();
 +        args->returnValue(v8::Null());
 +    } else {
 +        args->returnValue(o);
 +    }
 +}
 +
 +// XXX used by QSGLoader
 +void QQmlComponentPrivate::initializeObjectWithInitialProperties(v8::Handle<v8::Object> qmlGlobal, v8::Handle<v8::Object> valuemap, QObject *toCreate)
 +{
 +    QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
 +    QV8Engine *v8engine = ep->v8engine();
 +
 +    v8::HandleScope handle_scope;
 +    v8::Context::Scope scope(v8engine->context());
 +    v8::Handle<v8::Value> ov = v8engine->newQObject(toCreate);
 +    Q_ASSERT(ov->IsObject());
 +    v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(ov);
 +
 +    if (!valuemap.IsEmpty()) {
 +        QQmlComponentExtension *e = componentExtension(v8engine);
 +        // Try catch isn't needed as the function itself is loaded with try/catch
 +        v8::Handle<v8::Value> function = e->initialProperties->Run(qmlGlobal);
 +        v8::Handle<v8::Value> args[] = { object, valuemap };
 +        v8::Handle<v8::Function>::Cast(function)->Call(v8engine->global(), 2, args);
 +    }
 +
 +    QQmlData *ddata = QQmlData::get(toCreate);
 +    Q_ASSERT(ddata);
 +    ddata->setImplicitDestructible();
 +}
 +
 +
 +QQmlComponentExtension::QQmlComponentExtension(QV8Engine *engine)
 +{
 +    v8::HandleScope handle_scope;
 +    v8::Context::Scope scope(engine->context());
 +
 +    forceCompletion = qPersistentNew(V8FUNCTION(QV8IncubatorResource::ForceCompletion, engine));
 +
 +    {
 +    v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
 +    ft->InstanceTemplate()->SetHasExternalResource(true);
 +    ft->InstanceTemplate()->SetInternalFieldCount(1);
 +    ft->InstanceTemplate()->SetAccessor(v8::String::New("onStatusChanged"), 
 +                                        QV8IncubatorResource::StatusChangedGetter, 
 +                                        QV8IncubatorResource::StatusChangedSetter);
 +    ft->InstanceTemplate()->SetAccessor(v8::String::New("status"),
 +                                        QV8IncubatorResource::StatusGetter);
 +    ft->InstanceTemplate()->SetAccessor(v8::String::New("object"), 
 +                                        QV8IncubatorResource::ObjectGetter); 
 +    ft->InstanceTemplate()->SetAccessor(v8::String::New("forceCompletion"), 
 +                                        QV8IncubatorResource::ForceCompletionGetter); 
 +    incubationConstructor = qPersistentNew(ft->GetFunction());
 +    }
 +
 +    {
 +#define INITIALPROPERTIES_SOURCE \
 +        "(function(object, values) {"\
 +            "try {"\
 +                "for(var property in values) {" \
 +                    "try {"\
 +                        "var properties = property.split(\".\");"\
 +                        "var o = object;"\
 +                        "for (var ii = 0; ii < properties.length - 1; ++ii) {"\
 +                            "o = o[properties[ii]];"\
 +                        "}"\
 +                        "o[properties[properties.length - 1]] = values[property];"\
 +                    "} catch(e) {}"\
 +                "}"\
 +            "} catch(e) {}"\
 +        "})"
 +    initialProperties = qPersistentNew(engine->qmlModeCompile(QLatin1String(INITIALPROPERTIES_SOURCE)));
 +#undef INITIALPROPERTIES_SOURCE
 +    }
 +}
 +
 +v8::Handle<v8::Value> QV8IncubatorResource::ObjectGetter(v8::Local<v8::String>, 
 +                                                          const v8::AccessorInfo& info)
 +{
 +    QV8IncubatorResource *r = v8_resource_check<QV8IncubatorResource>(info.This());
 +    return r->engine->newQObject(r->object());
 +}
 +
 +v8::Handle<v8::Value> QV8IncubatorResource::ForceCompletionGetter(v8::Local<v8::String>, 
 +                                                                  const v8::AccessorInfo& info)
 +{
 +    QV8IncubatorResource *r = v8_resource_check<QV8IncubatorResource>(info.This());
 +    return componentExtension(r->engine)->forceCompletion;
 +}
 +
 +v8::Handle<v8::Value> QV8IncubatorResource::ForceCompletion(const v8::Arguments &args) 
 +{
 +    QV8IncubatorResource *r = v8_resource_cast<QV8IncubatorResource>(args.This());
 +    if (!r)
 +        V8THROW_TYPE("Not an incubator object");
 +
 +    r->forceCompletion();
 +
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> QV8IncubatorResource::StatusGetter(v8::Local<v8::String>, 
 +                                                         const v8::AccessorInfo& info)
 +{
 +    QV8IncubatorResource *r = v8_resource_check<QV8IncubatorResource>(info.This());
 +    return v8::Integer::NewFromUnsigned(r->status());
 +}
 +
 +v8::Handle<v8::Value> QV8IncubatorResource::StatusChangedGetter(v8::Local<v8::String>, 
 +                                                                 const v8::AccessorInfo& info)
 +{
 +    return info.This()->GetInternalField(0);
 +}
 +
 +void QV8IncubatorResource::StatusChangedSetter(v8::Local<v8::String>, v8::Local<v8::Value> value, 
 +                                                const v8::AccessorInfo& info)
 +{
 +    info.This()->SetInternalField(0, value);
 +}
 +
 +QQmlComponentExtension::~QQmlComponentExtension()
 +{
 +    qPersistentDispose(incubationConstructor);
 +    qPersistentDispose(initialProperties);
 +    qPersistentDispose(forceCompletion);
 +}
 +
 +QV8IncubatorResource::QV8IncubatorResource(QV8Engine *engine, IncubationMode m)
 +: QV8ObjectResource(engine), QQmlIncubator(m)
 +{
 +}
 +
 +void QV8IncubatorResource::setInitialState(QObject *o)
 +{
 +    QQmlComponent_setQmlParent(o, parent);
 +
 +    if (!valuemap.IsEmpty()) {
 +        QQmlComponentExtension *e = componentExtension(engine);
 +
 +        v8::HandleScope handle_scope;
 +        v8::Context::Scope scope(engine->context());
 +
 +        v8::Handle<v8::Value> function = e->initialProperties->Run(qmlGlobal);
 +        v8::Handle<v8::Value> args[] = { engine->newQObject(o), valuemap };
 +        v8::Handle<v8::Function>::Cast(function)->Call(engine->global(), 2, args);
 +
 +        qPersistentDispose(valuemap);
 +        qPersistentDispose(qmlGlobal);
 +    }
 +}
 +    
 +void QV8IncubatorResource::dispose()
 +{
 +    qPersistentDispose(valuemap);
 +    qPersistentDispose(qmlGlobal);
 +    // No further status changes are forthcoming, so we no long need a self reference
 +    qPersistentDispose(me);
 +}
 +
 +void QV8IncubatorResource::statusChanged(Status s)
 +{
 +    if (s == Ready) {
 +        Q_ASSERT(QQmlData::get(object()));
 +        QQmlData::get(object())->setImplicitDestructible();
 +    }
 +
 +    if (!me.IsEmpty()) { // Will be false in synchronous mode
 +        v8::HandleScope scope;
 +        v8::Local<v8::Value> callback = me->GetInternalField(0);
 +
 +        if (!callback.IsEmpty() && !callback->IsUndefined()) {
 +
 +            if (callback->IsFunction()) {
 +                v8::Context::Scope context_scope(engine->context());
 +                v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(callback);
 +                v8::Handle<v8::Value> args[] = { v8::Integer::NewFromUnsigned(s) };
 +                v8::TryCatch tc;
 +                f->Call(me, 1, args);
 +                if (tc.HasCaught()) {
 +                    QQmlError error;
 +                    QQmlExpressionPrivate::exceptionToError(tc.Message(), error);
 +                    QQmlEnginePrivate::warning(QQmlEnginePrivate::get(engine->engine()),
 +                                                       error);
 +                }
 +            }
 +        }
 +    }
 +
 +    if (s == Ready || s == Error) 
 +        dispose();
 +}
 +
 +QT_END_NAMESPACE
index 731fb6a,0000000..b03dd68
mode 100644,000000..100644
--- /dev/null
@@@ -1,129 -1,0 +1,131 @@@
-     QQmlComponentPrivate() : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0) {}
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLCOMPONENT_P_H
 +#define QQMLCOMPONENT_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 "qqmlcomponent.h"
 +
 +#include <private/qv8_p.h>
 +#include "qqmlengine_p.h"
 +#include "qqmltypeloader_p.h"
 +#include <private/qbitfield_p.h>
 +#include "qqmlvme_p.h"
 +#include "qqmlerror.h"
 +#include "qqml.h"
++#include "../debugger/qqmlprofilerservice_p.h"
 +
 +#include <QtCore/QString>
 +#include <QtCore/QStringList>
 +#include <QtCore/QList>
 +
 +#include <private/qobject_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QV8Engine;
 +
 +class QQmlComponent;
 +class QQmlEngine;
 +class QQmlCompiledData;
 +
 +class QQmlComponentAttached;
 +class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public QQmlTypeData::TypeDataCallback
 +{
 +    Q_DECLARE_PUBLIC(QQmlComponent)
 +        
 +public:
++    QQmlComponentPrivate() : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0), profiler(0) {}
 +
 +    QObject *beginCreate(QQmlContextData *);
 +    void completeCreate();
 +    void initializeObjectWithInitialProperties(v8::Handle<v8::Object> qmlGlobal, v8::Handle<v8::Object> valuemap, QObject *toCreate);
 +
 +    QQmlTypeData *typeData;
 +    virtual void typeDataReady(QQmlTypeData *);
 +    virtual void typeDataProgress(QQmlTypeData *, qreal);
 +    
 +    void fromTypeData(QQmlTypeData *data);
 +
 +    QUrl url;
 +    qreal progress;
 +
 +    int start;
 +    QQmlCompiledData *cc;
 +
 +    struct ConstructionState {
 +        ConstructionState() : completePending(false) {}
 +
 +        QQmlVME vme;
 +        QList<QQmlError> errors;
 +        bool completePending;
 +    };
 +    ConstructionState state;
 +
 +    static void beginDeferred(QQmlEnginePrivate *enginePriv, QObject *object, 
 +                              ConstructionState *state);
 +    static void complete(QQmlEnginePrivate *enginePriv, ConstructionState *state);
 +
 +    QQmlEngine *engine;
 +    QQmlGuardedContextData creationContext;
++    QQmlObjectCreatingProfiler *profiler;
 +
 +    void clear();
 +
 +    static QQmlComponentPrivate *get(QQmlComponent *c) {
 +        return static_cast<QQmlComponentPrivate *>(QObjectPrivate::get(c));
 +    }
 +};
 +
 +QT_END_NAMESPACE
 +
 +#endif // QQMLCOMPONENT_P_H
index 8cfe635,0000000..ee5a0c9
mode 100644,000000..100644
--- /dev/null
@@@ -1,1854 -1,0 +1,1854 @@@
-     Q_ASSERT(inProgressCreations == 0);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlengine_p.h"
 +#include "qqmlengine.h"
 +#include "qqmlcomponentattached_p.h"
 +
 +#include "qqmlcontext_p.h"
 +#include "qqmlcompiler_p.h"
 +#include "qqml.h"
 +#include "qqmlcontext.h"
 +#include "qqmlexpression.h"
 +#include "qqmlcomponent.h"
 +#include "qqmlbinding_p_p.h"
 +#include "qqmlvme_p.h"
 +#include <private/qqmlenginedebugservice_p.h>
 +#include "qqmlstringconverters_p.h"
 +#include "qqmlxmlhttprequest_p.h"
 +#include "qqmlscriptstring.h"
 +#include "qqmlglobal_p.h"
 +#include "qquicklistmodel_p.h"
 +#include "qquickworkerscript_p.h"
 +#include "qqmlcomponent_p.h"
 +#include "qqmlnetworkaccessmanagerfactory.h"
 +#include "qqmlimageprovider.h"
 +#include "qqmldirparser_p.h"
 +#include "qqmlextensioninterface.h"
 +#include "qqmllist_p.h"
 +#include "qqmltypenamecache_p.h"
 +#include "qqmlnotifier_p.h"
 +#include <private/qqmlprofilerservice_p.h>
 +#include <private/qquickapplication_p.h>
 +#include <private/qv8debugservice_p.h>
 +#include <private/qdebugmessageservice_p.h>
 +#include "qqmlincubator.h"
 +#include <private/qv8profilerservice_p.h>
 +
 +#include <QtCore/qstandardpaths.h>
 +#include <QtCore/qsettings.h>
 +
 +#include <QtCore/qmetaobject.h>
 +#include <QNetworkAccessManager>
 +#include <QDebug>
 +#include <QMetaObject>
 +#include <QtCore/qcoreapplication.h>
 +#include <QtCore/qdir.h>
 +#include <QtCore/qmutex.h>
 +#include <QtNetwork/qnetworkconfigmanager.h>
 +
 +#include <private/qobject_p.h>
 +
 +#include <private/qqmllocale_p.h>
 +
 +#ifdef Q_OS_WIN // for %APPDATA%
 +#include <qt_windows.h>
 +#include <qlibrary.h>
 +#include <windows.h>
 +
 +#define CSIDL_APPDATA         0x001a  // <username>\Application Data
 +#endif
 +
 +Q_DECLARE_METATYPE(QQmlProperty)
 +
 +QT_BEGIN_NAMESPACE
 +
 +void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
 +{
 +    QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
 +    QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
 +}
 +
 +/*!
 +  \qmlclass QtObject QObject
 +  \ingroup qml-utility-elements
 +  \since 4.7
 +  \brief The QtObject element is the most basic element in QML.
 +
 +  The QtObject element is a non-visual element which contains only the
 +  objectName property.
 +
 +  It can be useful to create a QtObject if you need an extremely
 +  lightweight element to enclose a set of custom properties:
 +
 +  \snippet doc/src/snippets/qml/qtobject.qml 0
 +
 +  It can also be useful for C++ integration, as it is just a plain
 +  QObject. See the QObject documentation for further details.
 +*/
 +/*!
 +  \qmlproperty string QtObject::objectName
 +  This property holds the QObject::objectName for this specific object instance.
 +
 +  This allows a C++ application to locate an item within a QML component
 +  using the QObject::findChild() method. For example, the following C++
 +  application locates the child \l Rectangle item and dynamically changes its
 +  \c color value:
 +
 +    \qml
 +    // MyRect.qml
 +
 +    import QtQuick 2.0
 +
 +    Item {
 +        width: 200; height: 200
 +
 +        Rectangle {
 +            anchors.fill: parent
 +            color: "red"
 +            objectName: "myRect"
 +        }
 +    }
 +    \endqml
 +
 +    \code
 +    // main.cpp
 +
 +    QQuickView view;
 +    view.setSource(QUrl::fromLocalFile("MyRect.qml"));
 +    view.show();
 +
 +    QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
 +    if (item)
 +        item->setProperty("color", QColor(Qt::yellow));
 +    \endcode
 +*/
 +
 +bool QQmlEnginePrivate::qml_debugging_enabled = false;
 +
 +void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
 +{
 +    qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
 +    qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
 +    qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
 +    qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
 +    qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
 +}
 +
 +void QQmlEnginePrivate::defineModule()
 +{
 +    registerBaseTypes("QtQuick", 2, 0);
 +    qmlRegisterType<QQmlBinding>();
 +    qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
 +    qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated.  Use Qt.locale()"));
 +}
 +
 +/*!
 +\qmlclass Qt QQmlEnginePrivate
 +  \ingroup qml-utility-elements
 +\brief The QML global Qt object provides useful enums and functions from Qt.
 +
 +\keyword QmlGlobalQtObject
 +
 +\brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
 +
 +The \c Qt object is a global object with utility functions, properties and enums.
 +
 +It is not instantiable; to use it, call the members of the global \c Qt object directly.
 +For example:
 +
 +\qml
 +import QtQuick 2.0
 +
 +Text {
 +    color: Qt.rgba(1, 0, 0, 1)
 +    text: Qt.md5("hello, world")
 +}
 +\endqml
 +
 +
 +\section1 Enums
 +
 +The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
 +the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
 +
 +
 +\section1 Types
 +The Qt object also contains helper functions for creating objects of specific
 +data types. This is primarily useful when setting the properties of an item
 +when the property has one of the following types:
 +
 +\list
 +\o \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
 +\o \c rect - use \l{Qt::rect()}{Qt.rect()}
 +\o \c point - use \l{Qt::point()}{Qt.point()}
 +\o \c size - use \l{Qt::size()}{Qt.size()}
 +\o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
 +\endlist
 +
 +There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
 +
 +\section1 Date/Time Formatters
 +
 +The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
 +
 +\list
 +    \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
 +    \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
 +    \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
 +\endlist
 +
 +The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
 +
 +
 +\section1 Dynamic Object Creation
 +The following functions on the global object allow you to dynamically create QML
 +items from files or strings. See \l{Dynamic Object Management in QML} for an overview
 +of their use.
 +
 +\list
 +    \o \l{Qt::createComponent()}{object Qt.createComponent(url)}
 +    \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
 +\endlist
 +*/
 +
 +
 +/*!
 +    \qmlproperty object Qt::application
 +    \since QtQuick 1.1
 +
 +    The \c application object provides access to global application state
 +    properties shared by many QML components.
 +
 +    Its properties are:
 +
 +    \table
 +    \row
 +    \o \c application.active
 +    \o
 +    This read-only property indicates whether the application is the top-most and focused
 +    application, and the user is able to interact with the application. The property
 +    is false when the application is in the background, the device keylock or screen
 +    saver is active, the screen backlight is turned off, or the global system dialog
 +    is being displayed on top of the application. It can be used for stopping and
 +    pausing animations, timers and active processing of data in order to save device
 +    battery power and free device memory and processor load when the application is not
 +    active.
 +
 +    \row
 +    \o \c application.layoutDirection
 +    \o
 +    This read-only property can be used to query the default layout direction of the
 +    application. On system start-up, the default layout direction depends on the
 +    application's language. The property has a value of \c Qt.RightToLeft in locales
 +    where text and graphic elements are read from right to left, and \c Qt.LeftToRight
 +    where the reading direction flows from left to right. You can bind to this
 +    property to customize your application layouts to support both layout directions.
 +
 +    Possible values are:
 +
 +    \list
 +    \o Qt.LeftToRight - Text and graphics elements should be positioned
 +                        from left to right.
 +    \o Qt.RightToLeft - Text and graphics elements should be positioned
 +                        from right to left.
 +    \endlist
 +
 +    \row
 +    \o \c application.inputPanel
 +    \o
 +    This read-only property allows access to application's QInputPanel object
 +    and all its properties and slots. See the QInputPanel documentation for
 +    further details. Deprecated in favor of Qt.InputMethod
 +    \endtable
 +
 +    The following example uses the \c application object to indicate
 +    whether the application is currently active:
 +
 +    \snippet doc/src/snippets/qml/application.qml document
 +
 +    \qmlproperty object Qt::inputMethod
 +    \since QtQuick 2.0
 +
 +    The \c inputMethod object allows access to application's QInputMethod object
 +    and all its properties and slots. See the QInputMethod documentation for
 +    further details.
 +*/
 +
 +
 +/*!
 +\qmlmethod object Qt::include(string url, jsobject callback)
 +
 +Includes another JavaScript file. This method can only be used from within JavaScript files,
 +and not regular QML files.
 +
 +This imports all functions from \a url into the current script's namespace.
 +
 +Qt.include() returns an object that describes the status of the operation.  The object has
 +a single property, \c {status}, that is set to one of the following values:
 +
 +\table
 +\header \o Symbol \o Value \o Description
 +\row \o result.OK \o 0 \o The include completed successfully.
 +\row \o result.LOADING \o 1 \o Data is being loaded from the network.
 +\row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
 +\row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
 +An additional \c exception property will be set in this case.
 +\endtable
 +
 +The \c status property will be updated as the operation progresses.
 +
 +If provided, \a callback is invoked when the operation completes.  The callback is passed
 +the same object as is returned from the Qt.include() call.
 +*/
 +// Qt.include() is implemented in qv8include.cpp
 +
 +
 +QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
 +: propertyCapture(0), rootContext(0), isDebugging(false),
 +  outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
 +  cleanup(0), erroredBindings(0), inProgressCreations(0), 
 +  workerScriptEngine(0), activeVME(0),
 +  networkAccessManager(0), networkAccessManagerFactory(0),
 +  scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
 +  incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
 +{
 +}
 +
 +QQmlEnginePrivate::~QQmlEnginePrivate()
 +{
-         if (QQmlDebugService::isDebuggingEnabled()) {
-             QQmlProfilerService::startRange(QQmlProfilerService::Creating);
++    if (inProgressCreations)
++        qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
 +
 +    while (cleanup) {
 +        QQmlCleanup *c = cleanup;
 +        cleanup = c->next;
 +        if (cleanup) cleanup->prev = &cleanup;
 +        c->next = 0;
 +        c->prev = 0;
 +        c->clear();
 +    }
 +
 +    doDeleteInEngineThread();
 +
 +    if (incubationController) incubationController->d = 0;
 +    incubationController = 0;
 +
 +    delete rootContext;
 +    rootContext = 0;
 +
 +    for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
 +        (*iter)->release();
 +    for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
 +        (*iter)->release();
 +    for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
 +        (*iter)->release();
 +    for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
 +        delete (*iter)->qobjectApi;
 +        delete *iter;
 +    }
 +}
 +
 +void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
 +{
 +    QObjectPrivate *p = QObjectPrivate::get(o);
 +    if (p->declarativeData) {
 +        QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
 +        if (d->ownContext && d->context) {
 +            d->context->destroy();
 +            d->context = 0;
 +        }
 +    }
 +}
 +
 +void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
 +{
 +    static_cast<QQmlData *>(d)->destroyed(o);
 +}
 +
 +void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
 +{
 +    static_cast<QQmlData *>(d)->parentChanged(o, p);
 +}
 +
 +void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
 +{
 +    static_cast<QQmlData *>(d)->objectNameChanged(o);
 +}
 +
 +void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
 +{
 +    QQmlData *ddata = QQmlData::get(object, false);
 +    if (!ddata) return; // Probably being deleted
 +
 +    QQmlNotifierEndpoint *ep = ddata->notify(index);
 +    if (ep) QQmlNotifier::emitNotify(ep);
 +}
 +
 +void QQmlEnginePrivate::init()
 +{
 +    Q_Q(QQmlEngine);
 +
 +    static bool firstTime = true;
 +    if (firstTime) {
 +        qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
 +
 +        firstTime = false;
 +    }
 +
 +    qRegisterMetaType<QVariant>("QVariant");
 +    qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
 +    qRegisterMetaType<QJSValue>("QJSValue");
 +    qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
 +    qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
 +    qRegisterMetaType<QList<int> >("QList<int>");
 +    qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
 +
 +    QQmlData::init();
 +
 +    v8engine()->setEngine(q);
 +
 +    rootContext = new QQmlContext(q,true);
 +
 +    if (QCoreApplication::instance()->thread() == q->thread() &&
 +        QQmlEngineDebugService::isDebuggingEnabled()) {
 +        isDebugging = true;
 +        QQmlEngineDebugService::instance()->addEngine(q);
 +        QV8DebugService::initialize(v8engine());
 +        QV8ProfilerService::initialize();
 +        QQmlProfilerService::initialize();
 +        QDebugMessageService::instance();
 +    }
 +
 +    QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
 +    offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
 +                         QDir::separator() + QLatin1String("QML") +
 +                         QDir::separator() + QLatin1String("OfflineStorage");
 +}
 +
 +QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
 +{
 +    Q_Q(QQmlEngine);
 +    if (!workerScriptEngine)
 +        workerScriptEngine = new QQuickWorkerScriptEngine(q);
 +    return workerScriptEngine;
 +}
 +
 +/*!
 +  \class QQmlEngine
 +  \since 4.7
 +  \brief The QQmlEngine class provides an environment for instantiating QML components.
 +  \mainclass
 +
 +  Each QML component is instantiated in a QQmlContext.
 +  QQmlContext's are essential for passing data to QML
 +  components.  In QML, contexts are arranged hierarchically and this
 +  hierarchy is managed by the QQmlEngine.
 +
 +  Prior to creating any QML components, an application must have
 +  created a QQmlEngine to gain access to a QML context.  The
 +  following example shows how to create a simple Text item.
 +
 +  \code
 +  QQmlEngine engine;
 +  QQmlComponent component(&engine);
 +  component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
 +  QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
 +
 +  //add item to view, etc
 +  ...
 +  \endcode
 +
 +  In this case, the Text item will be created in the engine's
 +  \l {QQmlEngine::rootContext()}{root context}.
 +
 +  \sa QQmlComponent QQmlContext
 +*/
 +
 +/*!
 +  Create a new QQmlEngine with the given \a parent.
 +*/
 +QQmlEngine::QQmlEngine(QObject *parent)
 +: QJSEngine(*new QQmlEnginePrivate(this), parent)
 +{
 +    Q_D(QQmlEngine);
 +    d->init();
 +}
 +
 +/*!
 +  Destroys the QQmlEngine.
 +
 +  Any QQmlContext's created on this engine will be
 +  invalidated, but not destroyed (unless they are parented to the
 +  QQmlEngine object).
 +*/
 +QQmlEngine::~QQmlEngine()
 +{
 +    Q_D(QQmlEngine);
 +    if (d->isDebugging) {
 +        QQmlEngineDebugService::instance()->remEngine(this);
 +    }
 +
 +    // if we are the parent of any of the qobject module api instances,
 +    // we need to remove them from our internal list, in order to prevent
 +    // a segfault in engine private dtor.
 +    QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
 +    QObject *currQObjectApi = 0;
 +    QQmlMetaType::ModuleApiInstance *currInstance = 0;
 +    foreach (const QQmlMetaType::ModuleApi &key, keys) {
 +        currInstance = d->moduleApiInstances.value(key);
 +        currQObjectApi = currInstance->qobjectApi;
 +        if (this->children().contains(currQObjectApi)) {
 +            delete currQObjectApi;
 +            delete currInstance;
 +            d->moduleApiInstances.remove(key);
 +        }
 +    }
 +
 +    // ensure we clean up QObjects with JS ownership
 +    d->v8engine()->gc();
 +
 +    if (d->incubationController)
 +        d->incubationController->d = 0;
 +}
 +
 +/*! \fn void QQmlEngine::quit()
 +    This signal is emitted when the QML loaded by the engine would like to quit.
 + */
 +
 +/*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
 +    This signal is emitted when \a warnings messages are generated by QML.
 + */
 +
 +/*!
 +  Clears the engine's internal component cache.
 +
 +  Normally the QQmlEngine caches components loaded from qml
 +  files.  This method clears this cache and forces the component to be
 +  reloaded.
 + */
 +void QQmlEngine::clearComponentCache()
 +{
 +    Q_D(QQmlEngine);
 +    d->typeLoader.clearCache();
 +}
 +
 +/*!
 +  Returns the engine's root context.
 +
 +  The root context is automatically created by the QQmlEngine.
 +  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.
 +*/
 +QQmlContext *QQmlEngine::rootContext() const
 +{
 +    Q_D(const QQmlEngine);
 +    return d->rootContext;
 +}
 +
 +/*!
 +  Sets the \a factory to use for creating QNetworkAccessManager(s).
 +
 +  QNetworkAccessManager is used for all network access by QML.  By
 +  implementing a factory it is possible to create custom
 +  QNetworkAccessManager with specialized caching, proxy and cookie
 +  support.
 +
 +  The factory must be set before executing the engine.
 +*/
 +void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
 +{
 +    Q_D(QQmlEngine);
 +    QMutexLocker locker(&d->mutex);
 +    d->networkAccessManagerFactory = factory;
 +}
 +
 +/*!
 +  Returns the current QQmlNetworkAccessManagerFactory.
 +
 +  \sa setNetworkAccessManagerFactory()
 +*/
 +QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
 +{
 +    Q_D(const QQmlEngine);
 +    return d->networkAccessManagerFactory;
 +}
 +
 +void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index) 
 +{
 +    if (activeVME) {
 +        activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
 +    } else {
 +        void *args[] = { 0 };
 +        QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
 +    }
 +}
 +
 +QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
 +{
 +    QMutexLocker locker(&mutex);
 +    QNetworkAccessManager *nam;
 +    if (networkAccessManagerFactory) {
 +        nam = networkAccessManagerFactory->create(parent);
 +    } else {
 +        nam = new QNetworkAccessManager(parent);
 +    }
 +
 +    return nam;
 +}
 +
 +QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
 +{
 +    Q_Q(const QQmlEngine);
 +    if (!networkAccessManager)
 +        networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
 +    return networkAccessManager;
 +}
 +
 +/*!
 +  Returns a common QNetworkAccessManager which can be used by any QML
 +  element instantiated by this engine.
 +
 +  If a QQmlNetworkAccessManagerFactory has been set and a
 +  QNetworkAccessManager has not yet been created, the
 +  QQmlNetworkAccessManagerFactory will be used to create the
 +  QNetworkAccessManager; otherwise the returned QNetworkAccessManager
 +  will have no proxy or cache set.
 +
 +  \sa setNetworkAccessManagerFactory()
 +*/
 +QNetworkAccessManager *QQmlEngine::networkAccessManager() const
 +{
 +    Q_D(const QQmlEngine);
 +    return d->getNetworkAccessManager();
 +}
 +
 +/*!
 +
 +  Sets the \a provider to use for images requested via the \e
 +  image: url scheme, with host \a providerId. The QQmlEngine
 +  takes ownership of \a provider.
 +
 +  Image providers enable support for pixmap and threaded image
 +  requests. See the QQmlImageProvider documentation for details on
 +  implementing and using image providers.
 +
 +  All required image providers should be added to the engine before any
 +  QML sources files are loaded.
 +
 +  \sa removeImageProvider()
 +*/
 +void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProvider *provider)
 +{
 +    Q_D(QQmlEngine);
 +    QMutexLocker locker(&d->mutex);
 +    d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProvider>(provider));
 +}
 +
 +/*!
 +  Returns the QQmlImageProvider set for \a providerId.
 +
 +  Returns the provider if it was found; otherwise returns 0.
 +*/
 +QQmlImageProvider *QQmlEngine::imageProvider(const QString &providerId) const
 +{
 +    Q_D(const QQmlEngine);
 +    QMutexLocker locker(&d->mutex);
 +    return d->imageProviders.value(providerId).data();
 +}
 +
 +/*!
 +  Removes the QQmlImageProvider for \a providerId.
 +
 +  \sa addImageProvider()
 +*/
 +void QQmlEngine::removeImageProvider(const QString &providerId)
 +{
 +    Q_D(QQmlEngine);
 +    QMutexLocker locker(&d->mutex);
 +    d->imageProviders.take(providerId);
 +}
 +
 +QQmlImageProvider::ImageType QQmlEnginePrivate::getImageProviderType(const QUrl &url)
 +{
 +    QMutexLocker locker(&mutex);
 +    QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
 +    locker.unlock();
 +    if (provider)
 +        return provider->imageType();
 +    return QQmlImageProvider::Invalid;
 +}
 +
 +QQuickTextureFactory *QQmlEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
 +{
 +    QMutexLocker locker(&mutex);
 +    QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
 +    locker.unlock();
 +    if (provider) {
 +        QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
 +        return provider->requestTexture(imageId, size, req_size);
 +    }
 +    return 0;
 +}
 +
 +QImage QQmlEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
 +{
 +    QMutexLocker locker(&mutex);
 +    QImage image;
 +    QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
 +    locker.unlock();
 +    if (provider) {
 +        QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
 +        image = provider->requestImage(imageId, size, req_size);
 +    }
 +    return image;
 +}
 +
 +QPixmap QQmlEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
 +{
 +    QMutexLocker locker(&mutex);
 +    QPixmap pixmap;
 +    QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
 +    locker.unlock();
 +    if (provider) {
 +        QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
 +        pixmap = provider->requestPixmap(imageId, size, req_size);
 +    }
 +    return pixmap;
 +}
 +
 +/*!
 +  Return the base URL for this engine.  The base URL is only used to
 +  resolve components when a relative URL is passed to the
 +  QQmlComponent constructor.
 +
 +  If a base URL has not been explicitly set, this method returns the
 +  application's current working directory.
 +
 +  \sa setBaseUrl()
 +*/
 +QUrl QQmlEngine::baseUrl() const
 +{
 +    Q_D(const QQmlEngine);
 +    if (d->baseUrl.isEmpty()) {
 +        return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
 +    } else {
 +        return d->baseUrl;
 +    }
 +}
 +
 +/*!
 +  Set the  base URL for this engine to \a url.
 +
 +  \sa baseUrl()
 +*/
 +void QQmlEngine::setBaseUrl(const QUrl &url)
 +{
 +    Q_D(QQmlEngine);
 +    d->baseUrl = url;
 +}
 +
 +/*!
 +  Returns true if warning messages will be output to stderr in addition
 +  to being emitted by the warnings() signal, otherwise false.
 +
 +  The default value is true.
 +*/
 +bool QQmlEngine::outputWarningsToStandardError() const
 +{
 +    Q_D(const QQmlEngine);
 +    return d->outputWarningsToStdErr;
 +}
 +
 +/*!
 +  Set whether warning messages will be output to stderr to \a enabled.
 +
 +  If \a enabled is true, any warning messages generated by QML will be
 +  output to stderr and emitted by the warnings() signal.  If \a enabled
 +  is false, on the warnings() signal will be emitted.  This allows
 +  applications to handle warning output themselves.
 +
 +  The default value is true.
 +*/
 +void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
 +{
 +    Q_D(QQmlEngine);
 +    d->outputWarningsToStdErr = enabled;
 +}
 +
 +/*!
 +  Attempt to free unused memory.
 +*/
 +void QQmlEngine::collectGarbage()
 +{
 +    QV8Engine::gc();
 +}
 +
 +/*!
 +  Returns the QQmlContext for the \a object, or 0 if no
 +  context has been set.
 +
 +  When the QQmlEngine instantiates a QObject, the context is
 +  set automatically.
 +  */
 +QQmlContext *QQmlEngine::contextForObject(const QObject *object)
 +{
 +    if(!object)
 +        return 0;
 +
 +    QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
 +
 +    QQmlData *data =
 +        static_cast<QQmlData *>(priv->declarativeData);
 +
 +    if (!data)
 +        return 0;
 +    else if (data->outerContext)
 +        return data->outerContext->asQQmlContext();
 +    else
 +        return 0;
 +}
 +
 +/*!
 +  Sets the QQmlContext 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 QQmlEngine instantiates a QObject, the context is
 +  set automatically.
 + */
 +void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
 +{
 +    if (!object || !context)
 +        return;
 +
 +    QQmlData *data = QQmlData::get(object, true);
 +    if (data->context) {
 +        qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
 +        return;
 +    }
 +
 +    QQmlContextData *contextData = QQmlContextData::get(context);
 +    contextData->addObject(object);
 +}
 +
 +/*!
 +  \enum QQmlEngine::ObjectOwnership
 +
 +  Ownership controls whether or not QML automatically destroys the
 +  QObject when the object is garbage collected by the JavaScript
 +  engine.  The two ownership options are:
 +
 +  \value CppOwnership The object is owned by C++ code, and will
 +  never be deleted by QML.  The JavaScript destroy() method cannot be
 +  used on objects with CppOwnership.  This option is similar to
 +  QScriptEngine::QtOwnership.
 +
 +  \value JavaScriptOwnership The object is owned by JavaScript.
 +  When the object is returned to QML as the return value of a method
 +  call or property access, QML will delete the object if there are no
 +  remaining JavaScript references to it and it has no
 +  QObject::parent().  This option is similar to
 +  QScriptEngine::ScriptOwnership.
 +
 +  Generally an application doesn't need to set an object's ownership
 +  explicitly.  QML uses a heuristic to set the default object
 +  ownership.  By default, an object that is created by QML has
 +  JavaScriptOwnership.  The exception to this are the root objects
 +  created by calling QQmlComponent::create() or
 +  QQmlComponent::beginCreate() which have CppOwnership by
 +  default.  The ownership of these root-level objects is considered to
 +  have been transferred to the C++ caller.
 +
 +  Objects not-created by QML have CppOwnership by default.  The
 +  exception to this is objects returned from a C++ method call.  The
 +  ownership of these objects is passed to JavaScript.
 +
 +  Calling setObjectOwnership() overrides the default ownership
 +  heuristic used by QML.
 +*/
 +
 +/*!
 +  Sets the \a ownership of \a object.
 +*/
 +void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
 +{
 +    if (!object)
 +        return;
 +
 +    QQmlData *ddata = QQmlData::get(object, true);
 +    if (!ddata)
 +        return;
 +
 +    ddata->indestructible = (ownership == CppOwnership)?true:false;
 +    ddata->explicitIndestructibleSet = true;
 +}
 +
 +/*!
 +  Returns the ownership of \a object.
 +*/
 +QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
 +{
 +    if (!object)
 +        return CppOwnership;
 +
 +    QQmlData *ddata = QQmlData::get(object, false);
 +    if (!ddata)
 +        return CppOwnership;
 +    else
 +        return ddata->indestructible?CppOwnership:JavaScriptOwnership;
 +}
 +
 +bool QQmlEngine::event(QEvent *e)
 +{
 +    Q_D(QQmlEngine);
 +    if (e->type() == QEvent::User) 
 +        d->doDeleteInEngineThread();
 +
 +    return QJSEngine::event(e);
 +}
 +
 +void QQmlEnginePrivate::doDeleteInEngineThread()
 +{
 +    QFieldList<Deletable, &Deletable::next> list;
 +    mutex.lock();
 +    list.copyAndClear(toDeleteInEngineThread);
 +    mutex.unlock();
 +
 +    while (Deletable *d = list.takeFirst())
 +        delete d;
 +}
 +
 +Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
 +{
 +    QQmlData *data = QQmlData::get(object);
 +
 +    if (data && data->deferredComponent) {
-             QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(object->metaObject()->className());
-             QQmlProfilerService::rangeData(QQmlProfilerService::Creating, typeName);
++        QQmlObjectCreatingProfiler prof;
++        if (prof.enabled) {
 +            QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
-                 QQmlProfilerService::rangeLocation(QQmlProfilerService::Creating, data->outerContext->url, data->lineNumber, data->columnNumber);
++            prof.setTypeName(type ? type->qmlTypeName()
++                                  : QString::fromUtf8(object->metaObject()->className()));
 +            if (data->outerContext)
-         QQmlProfilerService::endRange(QQmlProfilerService::Creating);
++                prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
 +        }
 +        QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
 +
 +        QQmlComponentPrivate::ConstructionState state;
 +        QQmlComponentPrivate::beginDeferred(ep, object, &state);
 +
 +        data->deferredComponent->release();
 +        data->deferredComponent = 0;
 +
 +        QQmlComponentPrivate::complete(ep, &state);
-   type version mapping and possibly declarative extensions plugins.
 +    }
 +}
 +
 +QQmlContext *qmlContext(const QObject *obj)
 +{
 +    return QQmlEngine::contextForObject(obj);
 +}
 +
 +QQmlEngine *qmlEngine(const QObject *obj)
 +{
 +    QQmlData *data = QQmlData::get(obj, false);
 +    if (!data || !data->context)
 +        return 0;
 +    return data->context->engine;
 +}
 +
 +QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
 +{
 +    QQmlData *data = QQmlData::get(object);
 +    if (!data)
 +        return 0; // Attached properties are only on objects created by QML
 +
 +    QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
 +    if (rv || !create)
 +        return rv;
 +
 +    QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
 +    if (!pf)
 +        return 0;
 +
 +    rv = pf(const_cast<QObject *>(object));
 +
 +    if (rv)
 +        data->attachedProperties()->insert(id, rv);
 +
 +    return rv;
 +}
 +
 +QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
 +                                     const QMetaObject *attachedMetaObject, bool create)
 +{
 +    if (*idCache == -1)
 +        *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
 +
 +    if (*idCache == -1 || !object)
 +        return 0;
 +
 +    return qmlAttachedPropertiesObjectById(*idCache, object, create);
 +}
 +
 +QQmlDebuggingEnabler::QQmlDebuggingEnabler()
 +{
 +#ifndef QQML_NO_DEBUG_PROTOCOL
 +    if (!QQmlEnginePrivate::qml_debugging_enabled) {
 +        qWarning("Qml debugging is enabled. Only use this in a safe environment!");
 +    }
 +    QQmlEnginePrivate::qml_debugging_enabled = true;
 +#endif
 +}
 +
 +
 +class QQmlDataExtended {
 +public:
 +    QQmlDataExtended();
 +    ~QQmlDataExtended();
 +
 +    QHash<int, QObject *> attachedProperties;
 +    QQmlNotifier objectNameNotifier;
 +};
 +
 +QQmlDataExtended::QQmlDataExtended()
 +{
 +}
 +
 +QQmlDataExtended::~QQmlDataExtended()
 +{
 +}
 +
 +void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
 +{
 +    if (endpoint->next)
 +        layout(endpoint->next);
 +
 +    int index = endpoint->sourceSignal;
 +    index = qMin(index, 0xFFFF - 1);
 +
 +    endpoint->next = notifies[index];
 +    if (endpoint->next) endpoint->next->prev = &endpoint->next;
 +    endpoint->prev = &notifies[index];
 +    notifies[index] = endpoint;
 +}
 +
 +void QQmlData::NotifyList::layout()
 +{
 +    Q_ASSERT(maximumTodoIndex >= notifiesSize);
 +
 +    if (todo) {
 +        QQmlNotifierEndpoint **old = notifies;
 +        const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
 +        notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
 +        const int memsetSize = (maximumTodoIndex - notifiesSize + 1) * 
 +                               sizeof(QQmlNotifierEndpoint*);
 +        memset(notifies + notifiesSize, 0, memsetSize);
 +
 +        if (notifies != old) {
 +            for (int ii = 0; ii < notifiesSize; ++ii)
 +                if (notifies[ii]) 
 +                    notifies[ii]->prev = &notifies[ii];
 +        }
 +
 +        notifiesSize = maximumTodoIndex + 1;
 +
 +        layout(todo);
 +    }
 +
 +    maximumTodoIndex = 0;
 +    todo = 0;
 +}
 +
 +void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
 +{
 +    if (!notifyList) {
 +        notifyList = (NotifyList *)malloc(sizeof(NotifyList));
 +        notifyList->connectionMask = 0;
 +        notifyList->maximumTodoIndex = 0;
 +        notifyList->notifiesSize = 0;
 +        notifyList->todo = 0;
 +        notifyList->notifies = 0;
 +    }
 +
 +    Q_ASSERT(!endpoint->isConnected());
 +
 +    index = qMin(index, 0xFFFF - 1);
 +    notifyList->connectionMask |= (1ULL << quint64(index % 64));
 +
 +    if (index < notifyList->notifiesSize) {
 +
 +        endpoint->next = notifyList->notifies[index];
 +        if (endpoint->next) endpoint->next->prev = &endpoint->next;
 +        endpoint->prev = &notifyList->notifies[index];
 +        notifyList->notifies[index] = endpoint;
 +
 +    } else {
 +        notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
 +
 +        endpoint->next = notifyList->todo;
 +        if (endpoint->next) endpoint->next->prev = &endpoint->next;
 +        endpoint->prev = &notifyList->todo;
 +        notifyList->todo = endpoint;
 +    }
 +}
 +
 +QQmlNotifier *QQmlData::objectNameNotifier() const
 +{
 +    if (!extendedData) extendedData = new QQmlDataExtended;
 +    return &extendedData->objectNameNotifier;
 +}
 +
 +QHash<int, QObject *> *QQmlData::attachedProperties() const
 +{
 +    if (!extendedData) extendedData = new QQmlDataExtended;
 +    return &extendedData->attachedProperties;
 +}
 +
 +void QQmlData::destroyed(QObject *object)
 +{
 +    if (deferredComponent)
 +        deferredComponent->release();
 +
 +    if (nextContextObject)
 +        nextContextObject->prevContextObject = prevContextObject;
 +    if (prevContextObject)
 +        *prevContextObject = nextContextObject;
 +
 +    QQmlAbstractBinding *binding = bindings;
 +    while (binding) {
 +        QQmlAbstractBinding *next = binding->m_nextBinding;
 +        binding->m_prevBinding = 0;
 +        binding->m_nextBinding = 0;
 +        binding->destroy();
 +        binding = next;
 +    }
 +
 +    if (bindingBits)
 +        free(bindingBits);
 +
 +    if (propertyCache)
 +        propertyCache->release();
 +
 +    if (ownContext && context)
 +        context->destroy();
 +
 +    while (guards) {
 +        QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
 +        *guard = (QObject *)0;
 +        guard->objectDestroyed(object);
 +    }
 +
 +    if (notifyList) {
 +        while (notifyList->todo)
 +            notifyList->todo->disconnect();
 +        for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
 +            while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
 +                ep->disconnect();
 +        }
 +        free(notifyList->notifies);
 +        free(notifyList);
 +    }
 +
 +    if (extendedData)
 +        delete extendedData;
 +
 +    v8object.Clear(); // The WeakReference handler will clean the actual handle
 +
 +    if (ownMemory)
 +        delete this;
 +}
 +
 +void QQmlData::parentChanged(QObject *object, QObject *parent)
 +{
 +    Q_UNUSED(object);
 +    Q_UNUSED(parent);
 +}
 +
 +void QQmlData::objectNameChanged(QObject *)
 +{
 +    if (extendedData) objectNameNotifier()->notify();
 +}
 +
 +bool QQmlData::hasBindingBit(int bit) const
 +{
 +    if (bindingBitsSize > bit)
 +        return bindingBits[bit / 32] & (1 << (bit % 32));
 +    else
 +        return false;
 +}
 +
 +void QQmlData::clearBindingBit(int bit)
 +{
 +    if (bindingBitsSize > bit)
 +        bindingBits[bit / 32] &= ~(1 << (bit % 32));
 +}
 +
 +void QQmlData::setBindingBit(QObject *obj, int bit)
 +{
 +    if (bindingBitsSize <= bit) {
 +        int props = obj->metaObject()->propertyCount();
 +        Q_ASSERT(bit < props);
 +
 +        int arraySize = (props + 31) / 32;
 +        int oldArraySize = bindingBitsSize / 32;
 +
 +        bindingBits = (quint32 *)realloc(bindingBits,
 +                                         arraySize * sizeof(quint32));
 +
 +        memset(bindingBits + oldArraySize,
 +               0x00,
 +               sizeof(quint32) * (arraySize - oldArraySize));
 +
 +        bindingBitsSize = arraySize * 32;
 +    }
 +
 +    bindingBits[bit / 32] |= (1 << (bit % 32));
 +}
 +
 +QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
 +{
 +    if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
 +        if (url.authority().isEmpty())
 +            return QLatin1Char(':') + url.path();
 +        return QString();
 +    }
 +    return url.toLocalFile();
 +}
 +
 +
 +static QString toLocalFile(const QString &url)
 +{
 +    if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
 +        return QString();
 +
 +    QString file = url.mid(7);
 +
 +    //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
 +
 +    // magic for drives on windows
 +    if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
 +        file.remove(0, 1);
 +
 +    return file;
 +}
 +
 +QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
 +{
 +    if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
 +        if (url.length() > 4)
 +            return QLatin1Char(':') + url.mid(4);
 +        return QString();
 +    }
 +
 +    return toLocalFile(url);
 +}
 +
 +void QQmlEnginePrivate::sendQuit()
 +{
 +    Q_Q(QQmlEngine);
 +    emit q->quit();
 +    if (q->receivers(SIGNAL(quit())) == 0) {
 +        qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
 +    }
 +}
 +
 +static void dumpwarning(const QQmlError &error)
 +{
 +    qWarning().nospace() << qPrintable(error.toString());
 +}
 +
 +static void dumpwarning(const QList<QQmlError> &errors)
 +{
 +    for (int ii = 0; ii < errors.count(); ++ii)
 +        dumpwarning(errors.at(ii));
 +}
 +
 +void QQmlEnginePrivate::warning(const QQmlError &error)
 +{
 +    Q_Q(QQmlEngine);
 +    q->warnings(QList<QQmlError>() << error);
 +    if (outputWarningsToStdErr)
 +        dumpwarning(error);
 +}
 +
 +void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
 +{
 +    Q_Q(QQmlEngine);
 +    q->warnings(errors);
 +    if (outputWarningsToStdErr)
 +        dumpwarning(errors);
 +}
 +
 +void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
 +{
 +    if (engine)
 +        QQmlEnginePrivate::get(engine)->warning(error);
 +    else
 +        dumpwarning(error);
 +}
 +
 +void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
 +{
 +    if (engine)
 +        QQmlEnginePrivate::get(engine)->warning(error);
 +    else
 +        dumpwarning(error);
 +}
 +
 +void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
 +{
 +    if (engine)
 +        engine->warning(error);
 +    else
 +        dumpwarning(error);
 +}
 +
 +void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
 +{
 +    if (engine)
 +        engine->warning(error);
 +    else
 +        dumpwarning(error);
 +}
 +
 +/*
 +   This function should be called prior to evaluation of any js expression,
 +   so that scarce resources are not freed prematurely (eg, if there is a
 +   nested javascript expression).
 + */
 +void QQmlEnginePrivate::referenceScarceResources()
 +{
 +    scarceResourcesRefCount += 1;
 +}
 +
 +/*
 +   This function should be called after evaluation of the js expression is
 +   complete, and so the scarce resources may be freed safely.
 + */
 +void QQmlEnginePrivate::dereferenceScarceResources()
 +{
 +    Q_ASSERT(scarceResourcesRefCount > 0);
 +    scarceResourcesRefCount -= 1;
 +
 +    // if the refcount is zero, then evaluation of the "top level"
 +    // expression must have completed.  We can safely release the
 +    // scarce resources.
 +    if (scarceResourcesRefCount == 0) {
 +        // iterate through the list and release them all.
 +        // note that the actual SRD is owned by the JS engine,
 +        // so we cannot delete the SRD; but we can free the
 +        // memory used by the variant in the SRD.
 +        while (ScarceResourceData *sr = scarceResources.first()) {
 +            sr->data = QVariant();
 +            scarceResources.remove(sr);
 +        }
 +    }
 +}
 +
 +/*!
 +  Adds \a path as a directory where the engine searches for
 +  installed modules in a URL-based directory structure.
 +  The \a path may be a local filesystem directory or a URL.
 +
 +  The newly added \a path will be first in the importPathList().
 +
 +  \sa setImportPathList(), {QML Modules}
 +*/
 +void QQmlEngine::addImportPath(const QString& path)
 +{
 +    Q_D(QQmlEngine);
 +    d->importDatabase.addImportPath(path);
 +}
 +
 +/*!
 +  Returns the list of directories where the engine searches for
 +  installed modules in a URL-based directory structure.
 +
 +  For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
 +  imports \c com.mycompany.Feature will cause the QQmlEngine to look
 +  in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
 +  provided by that module. A \c qmldir file is required for defining the
++  type version mapping and possibly QML extensions plugins.
 +
 +  By default, the list contains the directory of the application executable,
 +  paths specified in the \c QML_IMPORT_PATH environment variable,
 +  and the builtin \c ImportsPath from QLibraryInfo.
 +
 +  \sa addImportPath() setImportPathList()
 +*/
 +QStringList QQmlEngine::importPathList() const
 +{
 +    Q_D(const QQmlEngine);
 +    return d->importDatabase.importPathList();
 +}
 +
 +/*!
 +  Sets \a paths as the list of directories where the engine searches for
 +  installed modules in a URL-based directory structure.
 +
 +  By default, the list contains the directory of the application executable,
 +  paths specified in the \c QML_IMPORT_PATH environment variable,
 +  and the builtin \c ImportsPath from QLibraryInfo.
 +
 +  \sa importPathList() addImportPath()
 +  */
 +void QQmlEngine::setImportPathList(const QStringList &paths)
 +{
 +    Q_D(QQmlEngine);
 +    d->importDatabase.setImportPathList(paths);
 +}
 +
 +
 +/*!
 +  Adds \a path as a directory where the engine searches for
 +  native plugins for imported modules (referenced in the \c qmldir file).
 +
 +  By default, the list contains only \c .,  i.e. the engine searches
 +  in the directory of the \c qmldir file itself.
 +
 +  The newly added \a path will be first in the pluginPathList().
 +
 +  \sa setPluginPathList()
 +*/
 +void QQmlEngine::addPluginPath(const QString& path)
 +{
 +    Q_D(QQmlEngine);
 +    d->importDatabase.addPluginPath(path);
 +}
 +
 +
 +/*!
 +  Returns the list of directories where the engine searches for
 +  native plugins for imported modules (referenced in the \c qmldir file).
 +
 +  By default, the list contains only \c .,  i.e. the engine searches
 +  in the directory of the \c qmldir file itself.
 +
 +  \sa addPluginPath() setPluginPathList()
 +*/
 +QStringList QQmlEngine::pluginPathList() const
 +{
 +    Q_D(const QQmlEngine);
 +    return d->importDatabase.pluginPathList();
 +}
 +
 +/*!
 +  Sets the list of directories where the engine searches for
 +  native plugins for imported modules (referenced in the \c qmldir file)
 +  to \a paths.
 +
 +  By default, the list contains only \c .,  i.e. the engine searches
 +  in the directory of the \c qmldir file itself.
 +
 +  \sa pluginPathList() addPluginPath()
 +  */
 +void QQmlEngine::setPluginPathList(const QStringList &paths)
 +{
 +    Q_D(QQmlEngine);
 +    d->importDatabase.setPluginPathList(paths);
 +}
 +
 +/*!
 +  Imports the plugin named \a filePath with the \a uri provided.
 +  Returns true if the plugin was successfully imported; otherwise returns false.
 +
 +  On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
 +
 +  The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
 +*/
 +bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
 +{
 +    Q_D(QQmlEngine);
 +    return d->importDatabase.importPlugin(filePath, uri, errors);
 +}
 +
 +/*!
 +  Imports the plugin named \a filePath with the \a uri provided.
 +  Returns true if the plugin was successfully imported; otherwise returns false.
 +
 +  On failure and if non-null, *\a errorString will be set to a message describing the failure.
 +
 +  The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
 +*/
 +bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
 +{
 +    Q_D(QQmlEngine);
 +    QList<QQmlError> errors;
 +    bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
 +    if (!errors.isEmpty()) {
 +        QString builtError;
 +        for (int i = 0; i < errors.size(); ++i) {
 +            builtError = QString(QLatin1String("%1\n        %2"))
 +                    .arg(builtError)
 +                    .arg(errors.at(i).toString());
 +        }
 +        *errorString = builtError;
 +    }
 +    return retn;
 +}
 +
 +/*!
 +  \property QQmlEngine::offlineStoragePath
 +  \brief the directory for storing offline user data
 +
 +  Returns the directory where SQL and other offline
 +  storage is placed.
 +
 +  QQuickWebView and the SQL databases created with openDatabase()
 +  are stored here.
 +
 +  The default is QML/OfflineStorage in the platform-standard
 +  user application data directory.
 +
 +  Note that the path may not currently exist on the filesystem, so
 +  callers wanting to \e create new files at this location should create
 +  it first - see QDir::mkpath().
 +*/
 +void QQmlEngine::setOfflineStoragePath(const QString& dir)
 +{
 +    Q_D(QQmlEngine);
 +    d->offlineStoragePath = dir;
 +}
 +
 +QString QQmlEngine::offlineStoragePath() const
 +{
 +    Q_D(const QQmlEngine);
 +    return d->offlineStoragePath;
 +}
 +
 +static void voidptr_destructor(void *v)
 +{
 +    void **ptr = (void **)v;
 +    delete ptr;
 +}
 +
 +static void *voidptr_constructor(const void *v)
 +{
 +    if (!v) {
 +        return new void*;
 +    } else {
 +        return new void*(*(void **)v);
 +    }
 +}
 +
 +QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
 +{
 +    Q_Q(QQmlEngine);
 +
 +    if (!mo->superClass()) {
 +        QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
 +        propertyCache.insert(mo, rv);
 +        return rv;
 +    } else {
 +        QQmlPropertyCache *super = cache(mo->superClass());
 +        QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
 +        propertyCache.insert(mo, rv);
 +        return rv;
 +    }
 +}
 +
 +QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
 +                                                                  QQmlError &error)
 +{
 +    QList<QQmlType *> types;
 +
 +    int maxMinorVersion = 0;
 +
 +    const QMetaObject *metaObject = type->metaObject();
 +
 +    while (metaObject) {
 +        QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
 +                                                            type->majorVersion(), minorVersion);
 +        if (t) {
 +            maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
 +            types << t;
 +        } else {
 +            types << 0;
 +        }
 +
 +        metaObject = metaObject->superClass();
 +    }
 +
 +    if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
 +        c->addref();
 +        typePropertyCache.insert(qMakePair(type, minorVersion), c);
 +        return c;
 +    }
 +
 +    QQmlPropertyCache *raw = cache(type->metaObject());
 +
 +    bool hasCopied = false;
 +
 +    for (int ii = 0; ii < types.count(); ++ii) {
 +        QQmlType *currentType = types.at(ii);
 +        if (!currentType)
 +            continue;
 +
 +        int rev = currentType->metaObjectRevision();
 +        int moIndex = types.count() - 1 - ii;
 +
 +        if (raw->allowedRevisionCache[moIndex] != rev) {
 +            if (!hasCopied) {
 +                raw = raw->copy();
 +                hasCopied = true;
 +            }
 +            raw->allowedRevisionCache[moIndex] = rev;
 +        }
 +    }
 +
 +    // Test revision compatibility - the basic rule is:
 +    //    * Anything that is excluded, cannot overload something that is not excluded *
 +
 +    // Signals override:
 +    //    * other signals and methods of the same name.
 +    //    * properties named on<Signal Name>
 +    //    * automatic <property name>Changed notify signals
 +
 +    // Methods override:
 +    //    * other methods of the same name
 +
 +    // Properties override:
 +    //    * other elements of the same name
 +
 +    bool overloadError = false;
 +    QString overloadName;
 +
 +#if 0
 +    for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
 +         !overloadError && iter != raw->stringCache.end();
 +         ++iter) {
 +
 +        QQmlPropertyData *d = *iter;
 +        if (raw->isAllowedInRevision(d))
 +            continue; // Not excluded - no problems
 +
 +        // check that a regular "name" overload isn't happening
 +        QQmlPropertyData *current = d;
 +        while (!overloadError && current) {
 +            current = d->overrideData(current);
 +            if (current && raw->isAllowedInRevision(current))
 +                overloadError = true;
 +        }
 +    }
 +#endif
 +
 +    if (overloadError) {
 +        if (hasCopied) raw->release();
 +
 +        error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1String(" ") + QString::number(type->majorVersion()) + QLatin1String(".") + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\".  This is an error in the type's implementation."));
 +        return 0;
 +    }
 +
 +    if (!hasCopied) raw->addref();
 +    typePropertyCache.insert(qMakePair(type, minorVersion), raw);
 +
 +    if (minorVersion != maxMinorVersion) {
 +        raw->addref();
 +        typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
 +    }
 +
 +    return raw;
 +}
 +
 +QQmlMetaType::ModuleApiInstance *
 +QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
 +{
 +    Locker locker(this);
 +
 +    QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
 +    if (!a) {
 +        a = new QQmlMetaType::ModuleApiInstance;
 +        a->scriptCallback = module.script;
 +        a->qobjectCallback = module.qobject;
 +        moduleApiInstances.insert(module, a);
 +    }
 +
 +    return a;
 +}
 +
 +bool QQmlEnginePrivate::isQObject(int t)
 +{
 +    Locker locker(this);
 +    return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
 +}
 +
 +QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
 +{
 +    Locker locker(this);
 +    int t = v.userType();
 +    if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
 +        if (ok) *ok = true;
 +        return *(QObject **)(v.constData());
 +    } else {
 +        return QQmlMetaType::toQObject(v, ok);
 +    }
 +}
 +
 +QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
 +{
 +    Locker locker(this);
 +    if (m_compositeTypes.contains(t))
 +        return QQmlMetaType::Object;
 +    else if (m_qmlLists.contains(t))
 +        return QQmlMetaType::List;
 +    else
 +        return QQmlMetaType::typeCategory(t);
 +}
 +
 +bool QQmlEnginePrivate::isList(int t) const
 +{
 +    Locker locker(this);
 +    return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
 +}
 +
 +int QQmlEnginePrivate::listType(int t) const
 +{
 +    Locker locker(this);
 +    QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
 +    if (iter != m_qmlLists.end())
 +        return *iter;
 +    else
 +        return QQmlMetaType::listType(t);
 +}
 +
 +const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
 +{
 +    Locker locker(this);
 +    QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
 +    if (iter != m_compositeTypes.end()) {
 +        return (*iter)->root;
 +    } else {
 +        QQmlType *type = QQmlMetaType::qmlType(t);
 +        return type?type->baseMetaObject():0;
 +    }
 +}
 +
 +const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
 +{
 +    Locker locker(this);
 +    QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
 +    if (iter != m_compositeTypes.end()) {
 +        return (*iter)->root;
 +    } else {
 +        QQmlType *type = QQmlMetaType::qmlType(t);
 +        return type?type->metaObject():0;
 +    }
 +}
 +
 +void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
 +{
 +    QByteArray name = data->root->className();
 +
 +    QByteArray ptr = name + '*';
 +    QByteArray lst = "QQmlListProperty<" + name + '>';
 +
 +    int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
 +                                           voidptr_constructor);
 +    int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
 +                                           voidptr_constructor);
 +
 +    data->addref();
 +
 +    Locker locker(this);
 +    m_qmlLists.insert(lst_type, ptr_type);
 +    m_compositeTypes.insert(ptr_type, data);
 +}
 +
 +bool QQml_isFileCaseCorrect(const QString &fileName)
 +{
 +#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
 +    QFileInfo info(fileName);
 +    const QString absolute = info.absoluteFilePath();
 +
 +#if defined(Q_OS_MAC)
 +    const QString canonical = info.canonicalFilePath();
 +#elif defined(Q_OS_WIN)
 +    wchar_t buffer[1024];
 +
 +    DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
 +    if (rv == 0 || rv >= 1024) return true;
 +    rv = ::GetLongPathName(buffer, buffer, 1024);
 +    if (rv == 0 || rv >= 1024) return true;
 +
 +    const QString canonical = QString::fromWCharArray(buffer);
 +#endif
 +
 +    const int absoluteLength = absolute.length();
 +    const int canonicalLength = canonical.length();
 +
 +    const int length = qMin(absoluteLength, canonicalLength);
 +    for (int ii = 0; ii < length; ++ii) {
 +        const QChar &a = absolute.at(absoluteLength - 1 - ii);
 +        const QChar &c = canonical.at(canonicalLength - 1 - ii);
 +
 +        if (a.toLower() != c.toLower())
 +            return true;
 +        if (a != c)
 +            return false;
 +    }
 +#else
 +    Q_UNUSED(fileName)
 +#endif
 +    return true;
 +}
 +
 +/*!
 +    \fn QQmlEngine *qmlEngine(const QObject *object)
 +    \relates QQmlEngine
 +
 +    Returns the QQmlEngine associated with \a object, if any.  This is equivalent to
 +    QQmlEngine::contextForObject(object)->engine(), but more efficient.
 +*/
 +
 +/*!
 +    \fn QQmlContext *qmlContext(const QObject *object)
 +    \relates QQmlEngine
 +
 +    Returns the QQmlContext associated with \a object, if any.  This is equivalent to
 +    QQmlEngine::contextForObject(object).
 +*/
 +
 +QT_END_NAMESPACE
index 3fbb80c,0000000..ecdbf21
mode 100644,000000..100644
--- /dev/null
@@@ -1,982 -1,0 +1,982 @@@
- static QQmlJavaScriptExpression::VTable QDeclarativeExpressionPrivate_jsvtable = {
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlexpression.h"
 +#include "qqmlexpression_p.h"
 +
 +#include "qqmlengine_p.h"
 +#include "qqmlcontext_p.h"
 +#include "qqmlrewrite_p.h"
 +#include "qqmlscriptstring_p.h"
 +#include "qqmlcompiler_p.h"
 +
 +#include <QtCore/qdebug.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +bool QQmlDelayedError::addError(QQmlEnginePrivate *e)
 +{
 +    if (!e) return false;
 +
 +    if (e->inProgressCreations == 0) return false; // Not in construction
 +
 +    if (prevError) return true; // Already in error chain
 +
 +    prevError = &e->erroredBindings;
 +    nextError = e->erroredBindings;
 +    e->erroredBindings = this;
 +    if (nextError) nextError->prevError = &nextError;
 +
 +    return true;
 +}
 +
 +QQmlJavaScriptExpression::QQmlJavaScriptExpression(VTable *v)
 +: m_vtable(v)
 +{
 +}
 +
 +QQmlJavaScriptExpression::~QQmlJavaScriptExpression()
 +{
 +    clearGuards();
 +}
 +
- : QQmlJavaScriptExpression(&QDeclarativeExpressionPrivate_jsvtable),
++static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = {
 +    QQmlExpressionPrivate::expressionIdentifier,
 +    QQmlExpressionPrivate::expressionChanged
 +};
 +
 +QQmlExpressionPrivate::QQmlExpressionPrivate()
++: QQmlJavaScriptExpression(&QQmlExpressionPrivate_jsvtable),
 +  expressionFunctionValid(true), expressionFunctionRewritten(false),
 +  extractExpressionFromFunction(false), line(-1), dataRef(0)
 +{
 +}
 +
 +QQmlExpressionPrivate::~QQmlExpressionPrivate()
 +{
 +    qPersistentDispose(v8qmlscope);
 +    qPersistentDispose(v8function);
 +    if (dataRef) dataRef->release();
 +    dataRef = 0;
 +}
 +
 +void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, 
 +                                         QObject *me)
 +{
 +    expression = expr;
 +
 +    QQmlAbstractExpression::setContext(ctxt);
 +    setScopeObject(me);
 +    expressionFunctionValid = false;
 +    expressionFunctionRewritten = false;
 +}
 +
 +void QQmlExpressionPrivate::init(QQmlContextData *ctxt, v8::Handle<v8::Function> func,
 +                                         QObject *me)
 +{
 +    QQmlAbstractExpression::setContext(ctxt);
 +    setScopeObject(me);
 +
 +    v8function = qPersistentNew<v8::Function>(func);
 +    setUseSharedContext(false);
 +    expressionFunctionValid = true;
 +    expressionFunctionRewritten = false;
 +    extractExpressionFromFunction = true;
 +}
 +
 +void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr,
 +                                         bool isRewritten, QObject *me, const QString &srcUrl,
 +                                         int lineNumber, int columnNumber)
 +{
 +    url = srcUrl;
 +    line = lineNumber;
 +    column = columnNumber;
 +
 +    expression = expr;
 +
 +    expressionFunctionValid = false;
 +    expressionFunctionRewritten = isRewritten;
 +
 +    QQmlAbstractExpression::setContext(ctxt);
 +    setScopeObject(me);
 +}
 +
 +void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QByteArray &expr,
 +                                         bool isRewritten, QObject *me, const QString &srcUrl,
 +                                         int lineNumber, int columnNumber)
 +{
 +    url = srcUrl;
 +    line = lineNumber;
 +    column = columnNumber;
 +
 +    if (isRewritten) {
 +        expressionFunctionValid = true;
 +        expressionFunctionRewritten = true;
 +        v8function = evalFunction(ctxt, me, expr.constData(), expr.length(),
 +                                  srcUrl, lineNumber, &v8qmlscope);
 +        setUseSharedContext(false);
 +
 +        expressionUtf8 = expr;
 +    } else {
 +        expression = QString::fromUtf8(expr);
 +
 +        expressionFunctionValid = false;
 +        expressionFunctionRewritten = isRewritten;
 +    }
 +
 +    QQmlAbstractExpression::setContext(ctxt);
 +    setScopeObject(me);
 +}
 +
 +// Callee owns the persistent handle
 +v8::Persistent<v8::Function>
 +QQmlExpressionPrivate::evalFunction(QQmlContextData *ctxt, QObject *scope,
 +                                            const char *code, int codeLength,
 +                                            const QString &filename, int line,
 +                                            v8::Persistent<v8::Object> *qmlscope)
 +{
 +    QQmlEngine *engine = ctxt->engine;
 +    QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
 +
 +    v8::HandleScope handle_scope;
 +    v8::Context::Scope ctxtscope(ep->v8engine()->context());
 +
 +    v8::TryCatch tc;
 +    v8::Local<v8::Object> scopeobject = ep->v8engine()->qmlScope(ctxt, scope);
 +    v8::Local<v8::Script> script = ep->v8engine()->qmlModeCompile(code, codeLength, filename, line);
 +    if (tc.HasCaught()) {
 +        QQmlError error;
 +        error.setDescription(QLatin1String("Exception occurred during function compilation"));
 +        error.setLine(line);
 +        error.setUrl(QUrl::fromLocalFile(filename));
 +        v8::Local<v8::Message> message = tc.Message();
 +        if (!message.IsEmpty())
 +            QQmlExpressionPrivate::exceptionToError(message, error);
 +        ep->warning(error);
 +        return v8::Persistent<v8::Function>();
 +    }
 +    v8::Local<v8::Value> result = script->Run(scopeobject);
 +    if (tc.HasCaught()) {
 +        QQmlError error;
 +        error.setDescription(QLatin1String("Exception occurred during function evaluation"));
 +        error.setLine(line);
 +        error.setUrl(QUrl::fromLocalFile(filename));
 +        v8::Local<v8::Message> message = tc.Message();
 +        if (!message.IsEmpty())
 +            QQmlExpressionPrivate::exceptionToError(message, error);
 +        ep->warning(error);
 +        return v8::Persistent<v8::Function>();
 +    }
 +    if (qmlscope) *qmlscope = qPersistentNew<v8::Object>(scopeobject);
 +    return qPersistentNew<v8::Function>(v8::Local<v8::Function>::Cast(result));
 +}
 +
 +// Callee owns the persistent handle
 +v8::Persistent<v8::Function> 
 +QQmlExpressionPrivate::evalFunction(QQmlContextData *ctxt, QObject *scope, 
 +                                            const QString &code, const QString &filename, int line,
 +                                            v8::Persistent<v8::Object> *qmlscope)
 +{
 +    QQmlEngine *engine = ctxt->engine;
 +    QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
 +
 +    v8::HandleScope handle_scope;
 +    v8::Context::Scope ctxtscope(ep->v8engine()->context());
 +
 +    v8::TryCatch tc;
 +    v8::Local<v8::Object> scopeobject = ep->v8engine()->qmlScope(ctxt, scope);
 +    v8::Local<v8::Script> script = ep->v8engine()->qmlModeCompile(code, filename, line);
 +    if (tc.HasCaught()) {
 +        QQmlError error;
 +        error.setDescription(QLatin1String("Exception occurred during function compilation"));
 +        error.setLine(line);
 +        error.setUrl(QUrl::fromLocalFile(filename));
 +        v8::Local<v8::Message> message = tc.Message();
 +        if (!message.IsEmpty())
 +            QQmlExpressionPrivate::exceptionToError(message, error);
 +        ep->warning(error);
 +        return v8::Persistent<v8::Function>();
 +    }
 +    v8::Local<v8::Value> result = script->Run(scopeobject);
 +    if (tc.HasCaught()) {
 +        QQmlError error;
 +        error.setDescription(QLatin1String("Exception occurred during function evaluation"));
 +        error.setLine(line);
 +        error.setUrl(QUrl::fromLocalFile(filename));
 +        v8::Local<v8::Message> message = tc.Message();
 +        if (!message.IsEmpty())
 +            QQmlExpressionPrivate::exceptionToError(message, error);
 +        ep->warning(error);
 +        return v8::Persistent<v8::Function>();
 +    }
 +    if (qmlscope) *qmlscope = qPersistentNew<v8::Object>(scopeobject);
 +    return qPersistentNew<v8::Function>(v8::Local<v8::Function>::Cast(result));
 +}
 +
 +QQmlExpression *
 +QQmlExpressionPrivate::create(QQmlContextData *ctxt, QObject *object,
 +                                      const QString &expr, bool isRewritten,
 +                                      const QString &url, int lineNumber, int columnNumber)
 +{
 +    return new QQmlExpression(ctxt, object, expr, isRewritten, url, lineNumber, columnNumber, *new QQmlExpressionPrivate);
 +}
 +
 +/*!
 +    \class QQmlExpression
 +    \since 4.7
 +    \brief The QQmlExpression class evaluates JavaScript in a QML context.
 +
 +    For example, given a file \c main.qml like this:
 +
 +    \qml
 +    import QtQuick 2.0
 +
 +    Item {
 +        width: 200; height: 200
 +    }
 +    \endqml
 +
 +    The following code evaluates a JavaScript expression in the context of the
 +    above QML:
 +
 +    \code
 +    QQmlEngine *engine = new QQmlEngine;
 +    QQmlComponent component(engine, QUrl::fromLocalFile("main.qml"));
 +
 +    QObject *myObject = component.create();
 +    QQmlExpression *expr = new QQmlExpression(engine->rootContext(), myObject, "width * 2");
 +    int result = expr->evaluate().toInt();  // result = 400
 +    \endcode
 +*/
 +
 +/*!
 +    Create an invalid QQmlExpression.
 +
 +    As the expression will not have an associated QQmlContext, this will be a
 +    null expression object and its value will always be an invalid QVariant.
 + */
 +QQmlExpression::QQmlExpression()
 +: QObject(*new QQmlExpressionPrivate, 0)
 +{
 +}
 +
 +/*!  \internal */
 +QQmlExpression::QQmlExpression(QQmlContextData *ctxt, 
 +                                               QObject *object, const QString &expr, bool isRewritten,
 +                                               const QString &url, int lineNumber, int columnNumber,
 +                                               QQmlExpressionPrivate &dd)
 +: QObject(dd, 0)
 +{
 +    Q_D(QQmlExpression);
 +    d->init(ctxt, expr, isRewritten, object, url, lineNumber, columnNumber);
 +}
 +
 +/*!  \internal */
 +QQmlExpression::QQmlExpression(QQmlContextData *ctxt,
 +                                               QObject *object, const QByteArray &expr,
 +                                               bool isRewritten,
 +                                               const QString &url, int lineNumber, int columnNumber,
 +                                               QQmlExpressionPrivate &dd)
 +: QObject(dd, 0)
 +{
 +    Q_D(QQmlExpression);
 +    d->init(ctxt, expr, isRewritten, object, url, lineNumber, columnNumber);
 +}
 +
 +/*!
 +    Create a QQmlExpression object that is a child of \a parent.
 +
 +    The \script provides the expression to be evaluated, the context to evaluate it in,
 +    and the scope object to evaluate it with.
 +
 +    This constructor is functionally equivalent to the following, but in most cases
 +    is more efficient.
 +    \code
 +    QQmlExpression expression(script.context(), script.scopeObject(), script.script(), parent);
 +    \endcode
 +
 +    \sa QQmlScriptString
 +*/
 +QQmlExpression::QQmlExpression(const QQmlScriptString &script, QObject *parent)
 +: QObject(*new QQmlExpressionPrivate, parent)
 +{
 +    Q_D(QQmlExpression);
 +    bool defaultConstruction = false;
 +
 +    int id = script.d.data()->bindingId;
 +    if (id < 0) {
 +        defaultConstruction = true;
 +    } else {
 +        QQmlContextData *ctxtdata = QQmlContextData::get(script.context());
 +
 +        QQmlEnginePrivate *engine = QQmlEnginePrivate::get(script.context()->engine());
 +        QQmlCompiledData *cdata = 0;
 +        QQmlTypeData *typeData = 0;
 +        if (engine && ctxtdata && !ctxtdata->url.isEmpty()) {
 +            typeData = engine->typeLoader.get(ctxtdata->url);
 +            cdata = typeData->compiledData();
 +        }
 +
 +        if (cdata)
 +            d->init(ctxtdata, cdata->primitives.at(id), true, script.scopeObject(),
 +                    cdata->name, script.d.data()->lineNumber, script.d.data()->columnNumber);
 +        else
 +           defaultConstruction = true;
 +
 +        if (cdata)
 +            cdata->release();
 +        if (typeData)
 +            typeData->release();
 +    }
 +
 +    if (defaultConstruction)
 +        d->init(QQmlContextData::get(script.context()), script.script(), script.scopeObject());
 +}
 +
 +/*!
 +    Create a QQmlExpression object that is a child of \a parent.
 +
 +    The \a expression JavaScript will be executed in the \a ctxt QQmlContext.
 +    If specified, the \a scope object's properties will also be in scope during
 +    the expression's execution.
 +*/
 +QQmlExpression::QQmlExpression(QQmlContext *ctxt,
 +                                               QObject *scope,
 +                                               const QString &expression,
 +                                               QObject *parent)
 +: QObject(*new QQmlExpressionPrivate, parent)
 +{
 +    Q_D(QQmlExpression);
 +    d->init(QQmlContextData::get(ctxt), expression, scope);
 +}
 +
 +/*! 
 +    \internal
 +*/
 +QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope,
 +                                               const QString &expression)
 +: QObject(*new QQmlExpressionPrivate, 0)
 +{
 +    Q_D(QQmlExpression);
 +    d->init(ctxt, expression, scope);
 +}
 +
 +/*!  \internal */
 +QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope,
 +                                               const QString &expression, QQmlExpressionPrivate &dd)
 +: QObject(dd, 0)
 +{
 +    Q_D(QQmlExpression);
 +    d->init(ctxt, expression, scope);
 +}
 +
 +/*!  
 +    \internal 
 +
 +    To avoid exposing v8 in the public API, functionPtr must be a pointer to a v8::Handle<v8::Function>.  
 +    For example:
 +        v8::Handle<v8::Function> function;
 +        new QQmlExpression(ctxt, scope, &function, ...);
 + */
 +QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope, void *functionPtr,
 +                                               QQmlExpressionPrivate &dd)
 +: QObject(dd, 0)
 +{
 +    v8::Handle<v8::Function> function = *(v8::Handle<v8::Function> *)functionPtr;
 +
 +    Q_D(QQmlExpression);
 +    d->init(ctxt, function, scope);
 +}
 +
 +/*!
 +    Destroy the QQmlExpression instance.
 +*/
 +QQmlExpression::~QQmlExpression()
 +{
 +}
 +
 +/*!
 +    Returns the QQmlEngine this expression is associated with, or 0 if there
 +    is no association or the QQmlEngine has been destroyed.
 +*/
 +QQmlEngine *QQmlExpression::engine() const
 +{
 +    Q_D(const QQmlExpression);
 +    return d->context()?d->context()->engine:0;
 +}
 +
 +/*!
 +    Returns the QQmlContext this expression is associated with, or 0 if there
 +    is no association or the QQmlContext has been destroyed.
 +*/
 +QQmlContext *QQmlExpression::context() const
 +{
 +    Q_D(const QQmlExpression);
 +    QQmlContextData *data = d->context();
 +    return data?data->asQQmlContext():0;
 +}
 +
 +/*!
 +    Returns the expression string.
 +*/
 +QString QQmlExpression::expression() const
 +{
 +    Q_D(const QQmlExpression);
 +    if (d->extractExpressionFromFunction && context()->engine()) {
 +        QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(context()->engine());
 +        v8::HandleScope handle_scope;
 +        v8::Context::Scope scope(v8engine->context());
 +
 +        return v8engine->toString(v8::Handle<v8::Value>(d->v8function));
 +    } else if (!d->expressionUtf8.isEmpty()) {
 +        return QString::fromUtf8(d->expressionUtf8);
 +    } else {
 +        return d->expression;
 +    }
 +}
 +
 +/*!
 +    Set the expression to \a expression.
 +*/
 +void QQmlExpression::setExpression(const QString &expression)
 +{
 +    Q_D(QQmlExpression);
 +
 +    d->resetNotifyOnValueChanged();
 +    d->expression = expression;
 +    d->expressionUtf8.clear();
 +    d->expressionFunctionValid = false;
 +    d->expressionFunctionRewritten = false;
 +    qPersistentDispose(d->v8function);
 +    qPersistentDispose(d->v8qmlscope);
 +}
 +
 +void QQmlExpressionPrivate::exceptionToError(v8::Handle<v8::Message> message, 
 +                                                     QQmlError &error)
 +{
 +    Q_ASSERT(!message.IsEmpty());
 +
 +    v8::Handle<v8::Value> name = message->GetScriptResourceName();
 +    v8::Handle<v8::String> description = message->Get();
 +    int lineNumber = message->GetLineNumber();
 +
 +    v8::Local<v8::String> file = name->IsString()?name->ToString():v8::Local<v8::String>();
 +    if (file.IsEmpty() || file->Length() == 0) 
 +        error.setUrl(QUrl(QLatin1String("<Unknown File>")));
 +    else 
 +        error.setUrl(QUrl(QV8Engine::toStringStatic(file)));
 +
 +    error.setLine(lineNumber);
 +    error.setColumn(-1);
 +
 +    QString qDescription = QV8Engine::toStringStatic(description);
 +    if (qDescription.startsWith(QLatin1String("Uncaught ")))
 +        qDescription = qDescription.mid(9 /* strlen("Uncaught ") */);
 +
 +    error.setDescription(qDescription);
 +}
 +
 +void QQmlJavaScriptExpression::setNotifyOnValueChanged(bool v)
 +{
 +    activeGuards.setFlagValue(v);
 +    if (!v) clearGuards();
 +}
 +
 +void QQmlJavaScriptExpression::resetNotifyOnValueChanged()
 +{
 +    clearGuards();
 +}
 +
 +v8::Local<v8::Value>
 +QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
 +                                           v8::Handle<v8::Function> function, bool *isUndefined)
 +{
 +    Q_ASSERT(context && context->engine);
 +
 +    if (function.IsEmpty() || function->IsUndefined()) {
 +        if (isUndefined) *isUndefined = true;
 +        return v8::Local<v8::Value>();
 +    }
 +
 +    QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
 +
 +    Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty());
 +    GuardCapture capture(context->engine, this);
 +
 +    QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture;
 +    ep->propertyCapture = notifyOnValueChanged()?&capture:0;
 +
 +
 +    if (notifyOnValueChanged())
 +        capture.guards.copyAndClearPrepend(activeGuards);
 +
 +    QQmlContextData *lastSharedContext = 0;
 +    QObject *lastSharedScope = 0;
 +
 +    bool sharedContext = useSharedContext();
 +
 +    // All code that follows must check with watcher before it accesses data members 
 +    // incase we have been deleted.
 +    DeleteWatcher watcher(this);
 +
 +    if (sharedContext) {
 +        lastSharedContext = ep->sharedContext;
 +        lastSharedScope = ep->sharedScope;
 +        ep->sharedContext = context;
 +        ep->sharedScope = scopeObject();
 +    }
 +
 +    v8::Local<v8::Value> result;
 +    {
 +        v8::TryCatch try_catch;
 +        v8::Handle<v8::Object> This = ep->v8engine()->global();
 +        if (scopeObject() && requiresThisObject()) {
 +            v8::Handle<v8::Value> value = ep->v8engine()->newQObject(scopeObject());
 +            if (value->IsObject()) This = v8::Handle<v8::Object>::Cast(value);
 +        }
 +
 +        result = function->Call(This, 0, 0);
 +
 +        if (isUndefined)
 +            *isUndefined = try_catch.HasCaught() || result->IsUndefined();
 +
 +        if (watcher.wasDeleted()) {
 +        } else if (try_catch.HasCaught()) {
 +            v8::Context::Scope scope(ep->v8engine()->context());
 +            v8::Local<v8::Message> message = try_catch.Message();
 +            if (!message.IsEmpty()) {
 +                QQmlExpressionPrivate::exceptionToError(message, delayedError()->error);
 +            } else {
 +                if (hasDelayedError()) delayedError()->error = QQmlError();
 +            }
 +        } else {
 +            if (hasDelayedError()) delayedError()->error = QQmlError();
 +        }
 +    }
 +
 +    if (sharedContext) {
 +        ep->sharedContext = lastSharedContext;
 +        ep->sharedScope = lastSharedScope;
 +    }
 +
 +    if (capture.errorString) {
 +        for (int ii = 0; ii < capture.errorString->count(); ++ii)
 +            qWarning("%s", qPrintable(capture.errorString->at(ii)));
 +        delete capture.errorString;
 +        capture.errorString = 0;
 +    }
 +
 +    while (Guard *g = capture.guards.takeFirst())
 +        g->Delete();
 +
 +    ep->propertyCapture = lastPropertyCapture;
 +
 +    return result;
 +}
 +
 +void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n)
 +{
 +    if (expression) {
 +
 +        // Try and find a matching guard
 +        while (!guards.isEmpty() && !guards.first()->isConnected(n))
 +            guards.takeFirst()->Delete();
 +
 +        Guard *g = 0;
 +        if (!guards.isEmpty()) {
 +            g = guards.takeFirst();
 +            g->cancelNotify();
 +            Q_ASSERT(g->isConnected(n));
 +        } else {
 +            g = Guard::New(expression, engine);
 +            g->connect(n);
 +        }
 +
 +        expression->activeGuards.prepend(g);
 +    }
 +}
 +
 +void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n)
 +{
 +    if (expression) {
 +        if (n == -1) {
 +            if (!errorString) {
 +                errorString = new QStringList;
 +                QString preamble = QLatin1String("QQmlExpression: Expression ") +
 +                                   expression->m_vtable->expressionIdentifier(expression) +
 +                                   QLatin1String(" depends on non-NOTIFYable properties:");
 +                errorString->append(preamble);
 +            }
 +
 +            const QMetaObject *metaObj = o->metaObject();
 +            QMetaProperty metaProp = metaObj->property(c);
 +
 +            QString error = QLatin1String("    ") +
 +                            QString::fromUtf8(metaObj->className()) +
 +                            QLatin1String("::") +
 +                            QString::fromUtf8(metaProp.name());
 +            errorString->append(error);
 +        } else {
 +
 +            // Try and find a matching guard
 +            while (!guards.isEmpty() && !guards.first()->isConnected(o, n))
 +                guards.takeFirst()->Delete();
 +
 +            Guard *g = 0;
 +            if (!guards.isEmpty()) {
 +                g = guards.takeFirst();
 +                g->cancelNotify();
 +                Q_ASSERT(g->isConnected(o, n));
 +            } else {
 +                g = Guard::New(expression, engine);
 +                g->connect(o, n);
 +            }
 +
 +            expression->activeGuards.prepend(g);
 +        }
 +    }
 +}
 +
 +void QQmlJavaScriptExpression::clearError()
 +{
 +    if (m_vtable.hasValue()) {
 +        m_vtable.value().error = QQmlError();
 +        m_vtable.value().removeError();
 +    }
 +}
 +
 +QQmlError QQmlJavaScriptExpression::error() const
 +{
 +    if (m_vtable.hasValue()) return m_vtable.constValue()->error;
 +    else return QQmlError();
 +}
 +
 +QQmlDelayedError *QQmlJavaScriptExpression::delayedError()
 +{
 +    return &m_vtable.value();
 +}
 +
 +void QQmlJavaScriptExpression::clearGuards()
 +{
 +    while (Guard *g = activeGuards.takeFirst())
 +        g->Delete();
 +}
 +
 +// Must be called with a valid handle scope
 +v8::Local<v8::Value> QQmlExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined)
 +{
 +    if (!expressionFunctionValid) {
 +        bool ok = true;
 +
 +        QQmlRewrite::RewriteBinding rewriteBinding;
 +        rewriteBinding.setName(name);
 +        QString code;
 +        if (expressionFunctionRewritten)
 +            code = expression;
 +        else
 +            code = rewriteBinding(expression, &ok);
 +
 +        if (ok) v8function = evalFunction(context(), scopeObject(), code, url, line, &v8qmlscope);
 +        setUseSharedContext(false);
 +        expressionFunctionValid = true;
 +    }
 +
 +
 +    if (secondaryScope) {
 +        v8::Local<v8::Value> result;
 +        QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
 +        QObject *restoreSecondaryScope = 0;
 +        restoreSecondaryScope = ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
 +        result = evaluate(context(), v8function, isUndefined);
 +        ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
 +        return result;
 +    } else {
 +        return evaluate(context(), v8function, isUndefined);
 +    }
 +}
 +
 +QVariant QQmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
 +{
 +    Q_Q(QQmlExpression);
 +
 +    if (!context() || !context()->isValid()) {
 +        qWarning("QQmlExpression: Attempted to evaluate an expression in an invalid context");
 +        return QVariant();
 +    }
 +
 +    QQmlEnginePrivate *ep = QQmlEnginePrivate::get(q->engine());
 +    QVariant rv;
 +
 +    ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
 +
 +    {
 +        v8::HandleScope handle_scope;
 +        v8::Context::Scope context_scope(ep->v8engine()->context());
 +        v8::Local<v8::Value> result = v8value(secondaryScope, isUndefined);
 +        rv = ep->v8engine()->toVariant(result, qMetaTypeId<QList<QObject*> >());
 +    }
 +
 +    ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
 +
 +    return rv;
 +}
 +
 +/*!
 +    Evaulates the expression, returning the result of the evaluation,
 +    or an invalid QVariant if the expression is invalid or has an error.
 +
 +    \a valueIsUndefined is set to true if the expression resulted in an
 +    undefined value.
 +
 +    \sa hasError(), error()
 +*/
 +QVariant QQmlExpression::evaluate(bool *valueIsUndefined)
 +{
 +    Q_D(QQmlExpression);
 +    return d->value(0, valueIsUndefined);
 +}
 +
 +/*!
 +Returns true if the valueChanged() signal is emitted when the expression's evaluated
 +value changes.
 +*/
 +bool QQmlExpression::notifyOnValueChanged() const
 +{
 +    Q_D(const QQmlExpression);
 +    return d->notifyOnValueChanged();
 +}
 +
 +/*!
 +  Sets whether the valueChanged() signal is emitted when the
 +  expression's evaluated value changes.
 +
 +  If \a notifyOnChange is true, the QQmlExpression will
 +  monitor properties involved in the expression's evaluation, and emit
 +  QQmlExpression::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 \a notifyOnChange is false (default), the QQmlExpression
 +  will not montitor properties involved in the expression's
 +  evaluation, and QQmlExpression::valueChanged() will never be
 +  emitted.  This is more efficient if an application wants a "one off"
 +  evaluation of the expression.
 +*/
 +void QQmlExpression::setNotifyOnValueChanged(bool notifyOnChange)
 +{
 +    Q_D(QQmlExpression);
 +    d->setNotifyOnValueChanged(notifyOnChange);
 +}
 +
 +/*!
 +    Returns the source file URL for this expression.  The source location must
 +    have been previously set by calling setSourceLocation().
 +*/
 +QString QQmlExpression::sourceFile() const
 +{
 +    Q_D(const QQmlExpression);
 +    return d->url;
 +}
 +
 +/*!
 +    Returns the source file line number for this expression.  The source location 
 +    must have been previously set by calling setSourceLocation().
 +*/
 +int QQmlExpression::lineNumber() const
 +{
 +    Q_D(const QQmlExpression);
 +    return d->line;
 +}
 +
 +/*!
 +    Returns the source file column number for this expression.  The source location
 +    must have been previously set by calling setSourceLocation().
 +*/
 +int QQmlExpression::columnNumber() const
 +{
 +    Q_D(const QQmlExpression);
 +    return d->column;
 +}
 +
 +/*!
 +    Set the location of this expression to \a line of \a url. This information
 +    is used by the script engine.
 +*/
 +void QQmlExpression::setSourceLocation(const QString &url, int line, int column)
 +{
 +    Q_D(QQmlExpression);
 +    d->url = url;
 +    d->line = line;
 +    d->column = column;
 +}
 +
 +/*!
 +    Returns the expression's scope object, if provided, otherwise 0.
 +
 +    In addition to data provided by the expression's QQmlContext, the scope
 +    object's properties are also in scope during the expression's evaluation.
 +*/
 +QObject *QQmlExpression::scopeObject() const
 +{
 +    Q_D(const QQmlExpression);
 +    return d->scopeObject();
 +}
 +
 +/*!
 +    Returns true if the last call to evaluate() resulted in an error,
 +    otherwise false.
 +    
 +    \sa error(), clearError()
 +*/
 +bool QQmlExpression::hasError() const
 +{
 +    Q_D(const QQmlExpression);
 +    return d->hasError();
 +}
 +
 +/*!
 +    Clear any expression errors.  Calls to hasError() following this will
 +    return false.
 +
 +    \sa hasError(), error()
 +*/
 +void QQmlExpression::clearError()
 +{
 +    Q_D(QQmlExpression);
 +    d->clearError();
 +}
 +
 +/*!
 +    Return any error from the last call to evaluate().  If there was no error,
 +    this returns an invalid QQmlError instance.
 +
 +    \sa hasError(), clearError()
 +*/
 +
 +QQmlError QQmlExpression::error() const
 +{
 +    Q_D(const QQmlExpression);
 +    return d->error();
 +}
 +
 +/*!
 +    \fn void QQmlExpression::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 QQmlExpression::evaluate()) before this signal will be emitted.
 +*/
 +
 +void QQmlExpressionPrivate::expressionChanged(QQmlJavaScriptExpression *e)
 +{
 +    QQmlExpressionPrivate *This = static_cast<QQmlExpressionPrivate *>(e);
 +    This->expressionChanged();
 +}
 +
 +void QQmlExpressionPrivate::expressionChanged()
 +{
 +    Q_Q(QQmlExpression);
 +    emit q->valueChanged();
 +}
 +
 +QString QQmlExpressionPrivate::expressionIdentifier(QQmlJavaScriptExpression *e)
 +{
 +    QQmlExpressionPrivate *This = static_cast<QQmlExpressionPrivate *>(e);
 +    return QLatin1String("\"") + This->expression + QLatin1String("\"");
 +}
 +
 +QQmlAbstractExpression::QQmlAbstractExpression()
 +: m_prevExpression(0), m_nextExpression(0)
 +{
 +}
 +
 +QQmlAbstractExpression::~QQmlAbstractExpression()
 +{
 +    if (m_prevExpression) {
 +        *m_prevExpression = m_nextExpression;
 +        if (m_nextExpression) 
 +            m_nextExpression->m_prevExpression = m_prevExpression;
 +    }
 +
 +    if (m_context.isT2())
 +        m_context.asT2()->_s = 0;
 +}
 +
 +QQmlContextData *QQmlAbstractExpression::context() const
 +{
 +    if (m_context.isT1()) return m_context.asT1();
 +    else return m_context.asT2()->_c;
 +}
 +
 +void QQmlAbstractExpression::setContext(QQmlContextData *context)
 +{
 +    if (m_prevExpression) {
 +        *m_prevExpression = m_nextExpression;
 +        if (m_nextExpression) 
 +            m_nextExpression->m_prevExpression = m_prevExpression;
 +        m_prevExpression = 0;
 +        m_nextExpression = 0;
 +    }
 +
 +    if (m_context.isT1()) m_context = context;
 +    else m_context.asT2()->_c = context;
 +
 +    if (context) {
 +        m_nextExpression = context->expressions;
 +        if (m_nextExpression) 
 +            m_nextExpression->m_prevExpression = &m_nextExpression;
 +        m_prevExpression = &context->expressions;
 +        context->expressions = this;
 +    }
 +}
 +
 +void QQmlAbstractExpression::refresh()
 +{
 +}
 +
 +bool QQmlAbstractExpression::isValid() const
 +{
 +    return context() != 0;
 +}
 +
 +QT_END_NAMESPACE
 +
 +#include <moc_qqmlexpression.cpp>
index 63ef1ad,0000000..1943194
mode 100644,000000..100644
--- /dev/null
@@@ -1,76 -1,0 +1,81 @@@
- Q_DECLARE_INTERFACE(QQmlExtensionInterface, "org.qt-project.Qt.QQmlExtensionInterface/1.0")
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLEXTENSIONINTERFACE_H
 +#define QQMLEXTENSIONINTERFACE_H
 +
 +#include <QtQml/qtqmlglobal.h>
 +#include <QtCore/qobject.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class QQmlEngine;
 +
 +class Q_QML_EXPORT QQmlTypesExtensionInterface
 +{
 +public:
 +    virtual ~QQmlTypesExtensionInterface() {}
 +    virtual void registerTypes(const char *uri) = 0;
 +};
 +
 +class Q_QML_EXPORT QQmlExtensionInterface : public QQmlTypesExtensionInterface
 +{
 +public:
 +    virtual ~QQmlExtensionInterface() {}
 +    virtual void initializeEngine(QQmlEngine *engine, const char *uri) = 0;
 +};
 +
++#define QQmlTypesExtensionInterface_iid "org.qt-project.Qt.QQmlTypesExtensionInterface"
++
 +Q_DECLARE_INTERFACE(QQmlTypesExtensionInterface, "org.qt-project.Qt.QQmlTypesExtensionInterface/1.0")
++
++#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface"
++
++Q_DECLARE_INTERFACE(QQmlExtensionInterface, QQmlExtensionInterface_iid)
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QQMLEXTENSIONINTERFACE_H
index d59cfc4,0000000..fe06925
mode 100644,000000..100644
--- /dev/null
@@@ -1,96 -1,0 +1,96 @@@
-     ~QQuickTextureFactory();
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLIMAGEPROVIDER_H
 +#define QQMLIMAGEPROVIDER_H
 +
 +#include <QtQml/qtqmlglobal.h>
 +#include <QtGui/qimage.h>
 +#include <QtGui/qpixmap.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class QQmlImageProviderPrivate;
 +class QSGTexture;
 +class QQuickCanvas;
 +
 +class Q_QML_EXPORT QQuickTextureFactory : public QObject
 +{
 +public:
 +    QQuickTextureFactory();
++    virtual ~QQuickTextureFactory();
 +
 +    virtual QSGTexture *createTexture(QQuickCanvas *canvas) const = 0;
 +    virtual QSize textureSize() const = 0;
 +    virtual int textureByteCount() const = 0;
 +};
 +
 +class Q_QML_EXPORT QQmlImageProvider
 +{
 +public:
 +    enum ImageType {
 +        Image,
 +        Pixmap,
 +        Texture,
 +        Invalid
 +    };
 +
 +    QQmlImageProvider(ImageType type);
 +    virtual ~QQmlImageProvider();
 +
 +    ImageType imageType() const;
 +
 +    virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize);
 +    virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize);
 +    virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize);
 +
 +private:
 +    QQmlImageProviderPrivate *d;
 +};
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QQMLIMAGEPROVIDER
index ee622ba,0000000..834d4bb
mode 100644,000000..100644
--- /dev/null
@@@ -1,696 -1,0 +1,697 @@@
- more objects to incubate.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlincubator.h"
 +#include "qqmlcomponent.h"
 +#include "qqmlincubator_p.h"
 +
 +#include "qqmlcompiler_p.h"
 +#include "qqmlexpression_p.h"
 +
 +// XXX TODO 
 +//   - check that the Component.onCompleted behavior is the same as 4.8 in the synchronous and 
 +//     async if nested cases
 +void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
 +{
 +    QQmlIncubatorPrivate *p = i.d;
 +
 +    QQmlIncubator::IncubationMode mode = i.incubationMode();
 +
 +    if (!incubationController)
 +        mode = QQmlIncubator::Synchronous;
 +
 +    if (mode == QQmlIncubator::AsynchronousIfNested) {
 +        mode = QQmlIncubator::Synchronous;
 +
 +        // Need to find the first constructing context and see if it is asynchronous
 +        QQmlIncubatorPrivate *parentIncubator = 0;
 +        QQmlContextData *cctxt = forContext;
 +        while (cctxt) {
 +            if (cctxt->activeVMEData) {
 +                parentIncubator = (QQmlIncubatorPrivate *)cctxt->activeVMEData;
 +                break;
 +            }
 +            cctxt = cctxt->parent;
 +        }
 +
 +        if (parentIncubator && parentIncubator->isAsynchronous) {
 +            mode = QQmlIncubator::Asynchronous;
 +            p->waitingOnMe = parentIncubator;
 +            parentIncubator->waitingFor.insert(p);
 +        }
 +    }
 +
 +    p->isAsynchronous = (mode != QQmlIncubator::Synchronous);
 +
 +    inProgressCreations++;
 +
 +    if (mode == QQmlIncubator::Synchronous) {
 +        typedef QQmlIncubatorPrivate IP;
 +        QRecursionWatcher<IP, &IP::recursion> watcher(p);
 +
 +        p->changeStatus(QQmlIncubator::Loading);
 +
 +        if (!watcher.hasRecursed()) {
 +            QQmlVME::Interrupt i;
 +            p->incubate(i);
 +        }
 +    } else {
 +        incubatorList.insert(p);
 +        incubatorCount++;
 +
 +        p->vmeGuard.guard(&p->vme);
 +        p->changeStatus(QQmlIncubator::Loading);
 +
 +        if (incubationController)
 +            incubationController->incubatingObjectCountChanged(incubatorCount);
 +    }
 +}
 +
 +/*!
 +Sets the engine's incubation \a controller.  The engine can only have one active controller 
 +and it does not take ownership of it.
 +
 +\sa incubationController()
 +*/
 +void QQmlEngine::setIncubationController(QQmlIncubationController *controller)
 +{
 +    Q_D(QQmlEngine);
 +    if (d->incubationController)
 +        d->incubationController->d = 0;
 +    d->incubationController = controller;
 +    if (controller) controller->d = d;
 +}
 +
 +/*!
 +Returns the currently set incubation controller, or 0 if no controller has been set.
 +
 +\sa setIncubationController()
 +*/
 +QQmlIncubationController *QQmlEngine::incubationController() const
 +{
 +    Q_D(const QQmlEngine);
 +    return d->incubationController;
 +}
 +
 +QQmlIncubatorPrivate::QQmlIncubatorPrivate(QQmlIncubator *q, 
 +                                                           QQmlIncubator::IncubationMode m)
 +: q(q), status(QQmlIncubator::Null), mode(m), isAsynchronous(false), progress(Execute),
 +  result(0), component(0), vme(this), waitingOnMe(0)
 +{
 +}
 +
 +QQmlIncubatorPrivate::~QQmlIncubatorPrivate()
 +{
 +}
 +
 +void QQmlIncubatorPrivate::clear()
 +{
 +    if (next.isInList()) {
 +        next.remove();
 +        Q_ASSERT(component);
 +        QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(component->engine);
 +        component->release();
 +        component = 0;
 +        enginePriv->incubatorCount--;
 +        QQmlIncubationController *controller = enginePriv->incubationController;
 +        if (controller)
 +            controller->incubatingObjectCountChanged(enginePriv->incubatorCount);
 +    } else if (component) {
 +        component->release();
 +        component = 0;
 +    }
 +    if (!rootContext.isNull()) {
 +        rootContext->activeVMEData = 0;
 +        rootContext = 0;
 +    }
 +
 +    if (nextWaitingFor.isInList()) {
 +        Q_ASSERT(waitingOnMe);
 +        nextWaitingFor.remove();
 +        waitingOnMe = 0;
 +    }
 +}
 +
 +/*!
 +\class QQmlIncubationController
 +\brief QQmlIncubationController instances drive the progress of QQmlIncubators
 +
 +In order to behave asynchronously and not introduce stutters or freezes in an application,
 +the process of creating objects a QQmlIncubators must be driven only during the
 +application's idle time.  QQmlIncubationController allows the application to control
 +exactly when, how often and for how long this processing occurs.
 +
 +A QQmlIncubationController derived instance should be created and set on a 
 +QQmlEngine by calling the QQmlEngine::setIncubationController() method.
 +Processing is then controlled by calling the QQmlIncubationController::incubateFor()
 +or QQmlIncubationController::incubateWhile() methods as dictated by the application's
 +requirements.
 +
 +For example, this is an example of a incubation controller that will incubate for a maximum
 +of 5 milliseconds out of every 16 milliseconds.
 +
 +\code
 +class PeriodicIncubationController : public QObject, 
 +                                     public QQmlIncubationController 
 +{
 +public:
 +    PeriodicIncubationController() { 
 +        startTimer(16); 
 +    }
 +
 +protected:
 +    virtual void timerEvent(QTimerEvent *) {
 +        incubateFor(5);
 +    }
 +};
 +\endcode
 +
 +Although the previous example would work, it is not optimal.  Real world incubation
 +controllers should try and maximize the amount of idle time they consume - rather
 +than a static amount like 5 milliseconds - while not disturbing the application.  
 +*/
 +
 +/*!
 +Create a new incubation controller.
 +*/
 +QQmlIncubationController::QQmlIncubationController()
 +: d(0)
 +{
 +}
 +
 +/*! \internal */
 +QQmlIncubationController::~QQmlIncubationController()
 +{
 +    if (d) QQmlEnginePrivate::get(d)->setIncubationController(0);
 +    d = 0;
 +}
 +
 +/*!
 +Return the QQmlEngine this incubation controller is set on, or 0 if it
 +has not been set on any engine.
 +*/
 +QQmlEngine *QQmlIncubationController::engine() const
 +{
 +    return QQmlEnginePrivate::get(d);
 +}
 +
 +/*!
 +Return the number of objects currently incubating.
 +*/
 +int QQmlIncubationController::incubatingObjectCount() const
 +{
 +    if (d)
 +        return d->incubatorCount;
 +    else 
 +        return 0;
 +}
 +
 +/*!
 +Called when the number of incubating objects changes.  \a incubatingObjectCount is the 
 +new number of incubating objects.
 +
 +The default implementation does nothing.
 +*/
 +void QQmlIncubationController::incubatingObjectCountChanged(int incubatingObjectCount)
 +{
 +    Q_UNUSED(incubatingObjectCount);
 +}
 +
 +void QQmlIncubatorPrivate::incubate(QQmlVME::Interrupt &i)
 +{
 +    if (!component)
 +        return;
 +    typedef QQmlIncubatorPrivate IP;
 +    QRecursionWatcher<IP, &IP::recursion> watcher(this);
 +
 +    QQmlEngine *engine = component->engine;
 +    QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
 +
 +    bool guardOk = vmeGuard.isOK();
 +    vmeGuard.clear();
 +
 +    if (!guardOk) {
 +        QQmlError error;
 +        error.setUrl(component->url);
 +        error.setDescription(QQmlComponent::tr("Object destroyed during incubation"));
 +        errors << error;
 +        progress = QQmlIncubatorPrivate::Completed;
 +
 +        goto finishIncubate;
 +    }
 +
 +    if (progress == QQmlIncubatorPrivate::Execute) {
 +        enginePriv->referenceScarceResources();
 +        QObject *tresult = vme.execute(&errors, i);
 +        enginePriv->dereferenceScarceResources();
 +
 +        if (watcher.hasRecursed())
 +            return;
 +
 +        result = tresult;
 +        if (errors.isEmpty() && result == 0) 
 +            goto finishIncubate;
 +
 +        if (result) {
 +            QQmlData *ddata = QQmlData::get(result);
 +            Q_ASSERT(ddata);
 +            ddata->indestructible = true;
 +
 +            q->setInitialState(result);
 +        }
 +
 +        if (watcher.hasRecursed())
 +            return;
 +
 +        if (errors.isEmpty())
 +            progress = QQmlIncubatorPrivate::Completing;
 +        else
 +            progress = QQmlIncubatorPrivate::Completed;
 +
 +        changeStatus(calculateStatus());
 +
 +        if (watcher.hasRecursed())
 +            return;
 +
 +        if (i.shouldInterrupt())
 +            goto finishIncubate;
 +    }
 +
 +    if (progress == QQmlIncubatorPrivate::Completing) {
 +        do {
 +            if (watcher.hasRecursed())
 +                return;
 +
 +            QQmlContextData *ctxt = vme.complete(i);
 +            if (ctxt) {
 +                rootContext = ctxt;
 +                progress = QQmlIncubatorPrivate::Completed;
 +                goto finishIncubate;
 +            }
 +        } while (!i.shouldInterrupt());
 +    }
 +
 +finishIncubate:
 +    if (progress == QQmlIncubatorPrivate::Completed && waitingFor.isEmpty()) {
 +        typedef QQmlIncubatorPrivate IP;
 +
 +        QQmlIncubatorPrivate *isWaiting = waitingOnMe;
 +        clear();
 +
 +        if (isWaiting) {
 +            QRecursionWatcher<IP, &IP::recursion> watcher(isWaiting);
 +            changeStatus(calculateStatus());
 +            if (!watcher.hasRecursed())
 +                isWaiting->incubate(i);
 +        } else {
 +            changeStatus(calculateStatus());
 +        }
 +
 +        enginePriv->inProgressCreations--;
 +
 +        if (0 == enginePriv->inProgressCreations) {
 +            while (enginePriv->erroredBindings) {
 +                enginePriv->warning(enginePriv->erroredBindings->error);
 +                enginePriv->erroredBindings->removeError();
 +            }
 +        }
 +    } else {
 +        vmeGuard.guard(&vme);
 +    }
 +}
 +
 +/*!
 +Incubate objects for \a msecs, or until there are no more objects to incubate.
 +*/
 +void QQmlIncubationController::incubateFor(int msecs)
 +{
 +    if (!d || d->incubatorCount == 0)
 +        return;
 +
 +    QQmlVME::Interrupt i(msecs * 1000000);
 +    i.reset();
 +    do {
 +        QQmlIncubatorPrivate *p = (QQmlIncubatorPrivate*)d->incubatorList.first();
 +        p->incubate(i);
 +    } while (d && d->incubatorCount != 0 && !i.shouldInterrupt());
 +}
 +
 +/*!
 +Incubate objects while the bool pointed to by \a flag is true, or until there are no
- void QQmlIncubationController::incubateWhile(bool *flag)
++more objects to incubate, or up to msecs if msecs is not zero.
 +
 +Generally this method is used in conjunction with a thread or a UNIX signal that sets
 +the bool pointed to by \a flag to false when it wants incubation to be interrupted.
 +*/
-     QQmlVME::Interrupt i(flag);
++void QQmlIncubationController::incubateWhile(volatile bool *flag, int msecs)
 +{
 +    if (!d || d->incubatorCount == 0)
 +        return;
 +
++    QQmlVME::Interrupt i(flag, msecs * 1000000);
++    i.reset();
 +    do {
 +        QQmlIncubatorPrivate *p = (QQmlIncubatorPrivate*)d->incubatorList.first();
 +        p->incubate(i);
 +    } while (d && d->incubatorCount != 0 && !i.shouldInterrupt());
 +}
 +
 +/*!
 +\class QQmlIncubator
 +\brief The QQmlIncubator class allows QML objects to be created asynchronously.
 +
 +Creating QML objects - like delegates in a view, or a new page in an application - can take
 +a noticable amount of time, especially on resource constrained mobile devices.  When an
 +application uses QQmlComponent::create() directly, the QML object instance is created
 +synchronously which, depending on the complexity of the object,  can cause noticable pauses or 
 +stutters in the application.
 +
 +The use of QQmlIncubator gives more control over the creation of a QML object, 
 +including allowing it to be created asynchronously using application idle time.  The following 
 +example shows a simple use of QQmlIncubator.
 +
 +\code
 +QQmlIncubator incubator;
 +component->create(incubator);
 +
 +while (incubator.isReady()) {
 +    QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
 +}
 +
 +QObject *object = incubator.object();
 +\endcode
 +
 +Asynchronous incubators are controlled by a QQmlIncubationController that is 
 +set on the QQmlEngine, which lets the engine know when the application is idle and
 +incubating objects should be processed.  If an incubation controller is not set on the
 +QQmlEngine, QQmlIncubator creates objects synchronously regardless of the
 +specified IncubationMode.  
 +
 +QQmlIncubator supports three incubation modes:
 +\list
 +\i Synchronous The creation occurs synchronously.  That is, once the 
 +QQmlComponent::create() call returns, the incubator will already be in either the
 +Error or Ready state.  A synchronous incubator has no real advantage compared to using
 +the synchronous creation methods on QQmlComponent directly, but it may simplify an 
 +application's implementation to use the same API for both synchronous and asynchronous 
 +creations.
 +
 +\i Asynchronous (default) The creation occurs asynchronously, assuming a 
 +QQmlIncubatorController is set on the QQmlEngine.  
 +
 +The incubator will remain in the Loading state until either the creation is complete or an error 
 +occurs.  The statusChanged() callback can be used to be notified of status changes.
 +
 +Applications should use the Asynchronous incubation mode to create objects that are not needed
 +immediately.  For example, the ListView element uses Asynchronous incubation to create objects
 +that are slightly off screen while the list is being scrolled.  If, during asynchronous creation,
 +the object is needed immediately the QQmlIncubator::forceCompletion() method can be called
 +to complete the creation process synchronously.
 +
 +\i AsynchronousIfNested The creation will occur asynchronously if part of a nested asynchronous 
 +creation, or synchronously if not.  
 +
 +In most scenarios where a QML element or component wants the appearance of a synchronous 
 +instantiation, it should use this mode.  
 +
 +This mode is best explained with an example.  When the ListView element is first created, it needs
 +to populate itself with an initial set of delegates to show.  If the ListView was 400 pixels high, 
 +and each delegate was 100 pixels high, it would need to create four initial delegate instances.  If
 +the ListView used the Asynchronous incubation mode, the ListView would always be created empty and
 +then, sometime later, the four initial elements would appear.  
 +
 +Conversely, if the ListView was to use the Synchronous incubation mode it would behave correctly 
 +but it may introduce stutters into the application.  As QML would have to stop and instantiate the 
 +ListView's delegates synchronously, if the ListView was part of a QML component that was being 
 +instantiated asynchronously this would undo much of the benefit of asynchronous instantiation.
 +
 +The AsynchronousIfNested mode reconciles this problem.  By using AsynchronousIfNested, the ListView
 +delegates are instantiated asynchronously if the ListView itself is already part of an asynchronous
 +instantiation, and synchronously otherwise.  In the case of a nested asynchronous instantiation, the
 +outer asynchronous instantiation will not complete until after all the nested instantiations have also
 +completed.  This ensures that by the time the outer asynchronous instantitation completes, inner 
 +elements like ListView have already completed loading their initial delegates.
 +
 +It is almost always incorrect to use the Synchronous incubation mode - elements or components that 
 +want the appearance of synchronous instantiation, but without the downsides of introducing freezes 
 +or stutters into the application, should use the AsynchronousIfNested incubation mode.
 +\endlist
 +*/
 +
 +/*!
 +Create a new incubator with the specified \a mode
 +*/
 +QQmlIncubator::QQmlIncubator(IncubationMode mode)
 +: d(new QQmlIncubatorPrivate(this, mode))
 +{
 +}
 +
 +/*! \internal */
 +QQmlIncubator::~QQmlIncubator()
 +{
 +    clear();
 +
 +    delete d; d = 0;
 +}
 +
 +/*!
 +\enum QQmlIncubator::IncubationMode
 +
 +Specifies the mode the incubator operates in.  Regardless of the incubation mode, a 
 +QQmlIncubator will behave synchronously if the QQmlEngine does not have
 +a QQmlIncubationController set.
 +
 +\value Asynchronous The object will be created asynchronously.
 +\value AsynchronousIfNested If the object is being created in a context that is already part
 +of an asynchronous creation, this incubator will join that existing incubation and execute 
 +asynchronously.  The existing incubation will not become Ready until both it and this 
 +incubation have completed.  Otherwise, the incubation will execute synchronously.
 +\value Synchronous The object will be created synchronously.
 +*/
 +
 +/*!
 +\enum QQmlIncubator::Status
 +
 +Specifies the status of the QQmlIncubator.
 +
 +\value Null Incubation is not in progress.  Call QQmlComponent::create() to begin incubating.
 +\value Ready The object is fully created and can be accessed by calling object().
 +\value Loading The object is in the process of being created.
 +\value Error An error occurred.  The errors can be access by calling errors().
 +*/
 +
 +/*!
 +Clears the incubator.  Any in-progress incubation is aborted.  If the incubator is in the 
 +Ready state, the created object is \b not deleted.
 +*/
 +void QQmlIncubator::clear()
 +{
 +    typedef QQmlIncubatorPrivate IP;
 +    QRecursionWatcher<IP, &IP::recursion> watcher(d);
 +
 +    Status s = status();
 +
 +    if (s == Null)
 +        return;
 +
 +    QQmlEnginePrivate *enginePriv = 0;
 +    if (s == Loading) {
 +        Q_ASSERT(d->component);
 +        enginePriv = QQmlEnginePrivate::get(d->component->engine);
 +        if (d->result) d->result->deleteLater();
 +        d->result = 0;
 +    }
 +
 +    d->clear();
 +
 +    d->vme.reset();
 +    d->vmeGuard.clear();
 +
 +    Q_ASSERT(d->component == 0);
 +    Q_ASSERT(d->waitingOnMe == 0);
 +    Q_ASSERT(d->waitingFor.isEmpty());
 +    Q_ASSERT(!d->nextWaitingFor.isInList());
 +
 +    d->errors.clear();
 +    d->progress = QQmlIncubatorPrivate::Execute;
 +    d->result = 0;
 +
 +    if (s == Loading) {
 +        Q_ASSERT(enginePriv);
 +
 +        enginePriv->inProgressCreations--;
 +        if (0 == enginePriv->inProgressCreations) {
 +            while (enginePriv->erroredBindings) {
 +                enginePriv->warning(enginePriv->erroredBindings->error);
 +                enginePriv->erroredBindings->removeError();
 +            }
 +        }
 +    }
 +
 +    d->changeStatus(Null);
 +}
 +
 +/*!
 +Force any in-progress incubation to finish synchronously.  Once this call
 +returns, the incubator will not be in the Loading state.
 +*/
 +void QQmlIncubator::forceCompletion()
 +{
 +    QQmlVME::Interrupt i;
 +    while (Loading == status()) {
 +        while (Loading == status() && !d->waitingFor.isEmpty())
 +            static_cast<QQmlIncubatorPrivate *>(d->waitingFor.first())->incubate(i);
 +        if (Loading == status())
 +            d->incubate(i);
 +    }
 +}
 +
 +/*!
 +Returns true if the incubator's status() is Null.
 +*/
 +bool QQmlIncubator::isNull() const
 +{
 +    return status() == Null;
 +}
 +
 +/*!
 +Returns true if the incubator's status() is Ready.
 +*/
 +bool QQmlIncubator::isReady() const
 +{
 +    return status() == Ready;
 +}
 +
 +/*!
 +Returns true if the incubator's status() is Error.
 +*/
 +bool QQmlIncubator::isError() const
 +{
 +    return status() == Error;
 +}
 +
 +/*!
 +Returns true if the incubator's status() is Loading.
 +*/
 +bool QQmlIncubator::isLoading() const
 +{
 +    return status() == Loading;
 +}
 +
 +/*!
 +Return the list of errors encountered while incubating the object.
 +*/
 +QList<QQmlError> QQmlIncubator::errors() const
 +{
 +    return d->errors;
 +}
 +
 +/*!
 +Return the incubation mode passed to the QQmlIncubator constructor.
 +*/
 +QQmlIncubator::IncubationMode QQmlIncubator::incubationMode() const
 +{
 +    return d->mode;
 +}
 +
 +/*!
 +Return the current status of the incubator.
 +*/
 +QQmlIncubator::Status QQmlIncubator::status() const
 +{
 +    return d->status;
 +}
 +
 +/*!
 +Return the incubated object if the status is Ready, otherwise 0.
 +*/
 +QObject *QQmlIncubator::object() const
 +{
 +    if (status() != Ready) return 0;
 +    else return d->result;
 +}
 +
 +/*!
 +Called when the status of the incubator changes.  \a status is the new status.
 +
 +The default implementation does nothing.
 +*/
 +void QQmlIncubator::statusChanged(Status status)
 +{
 +    Q_UNUSED(status);
 +}
 +
 +/*!
 +Called after the object is first created, but before property bindings are
 +evaluated and, if applicable, QQmlParserStatus::componentComplete() is
 +called.  This is equivalent to the point between QQmlComponent::beginCreate()
 +and QQmlComponent::endCreate(), and can be used to assign initial values
 +to the object's properties.
 +
 +The default implementation does nothing.
 +*/
 +void QQmlIncubator::setInitialState(QObject *object)
 +{
 +    Q_UNUSED(object);
 +}
 +
 +void QQmlIncubatorPrivate::changeStatus(QQmlIncubator::Status s)
 +{
 +    if (s == status) 
 +        return;
 +
 +    status = s;
 +    q->statusChanged(status);
 +}
 +
 +QQmlIncubator::Status QQmlIncubatorPrivate::calculateStatus() const
 +{
 +    if (!errors.isEmpty()) 
 +        return QQmlIncubator::Error;
 +    else if (result && progress == QQmlIncubatorPrivate::Completed && 
 +             waitingFor.isEmpty()) 
 +        return QQmlIncubator::Ready;
 +    else if (component) 
 +        return QQmlIncubator::Loading;
 +    else 
 +        return QQmlIncubator::Null;
 +}
 +
index 5d8ae7d,0000000..2fb2aaf
mode 100644,000000..100644
--- /dev/null
@@@ -1,129 -1,0 +1,130 @@@
-     void incubateWhile(bool *flag);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLINCUBATOR_H
 +#define QQMLINCUBATOR_H
 +
++#include <QtQml/qtqmlglobal.h>
 +#include <QtQml/qqmlerror.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class QQmlEngine;
 +
 +class QQmlIncubatorPrivate;
 +class Q_QML_EXPORT QQmlIncubator
 +{
 +    Q_DISABLE_COPY(QQmlIncubator)
 +public:
 +    enum IncubationMode {
 +        Asynchronous,
 +        AsynchronousIfNested,
 +        Synchronous
 +    };
 +    enum Status { 
 +        Null, 
 +        Ready, 
 +        Loading, 
 +        Error 
 +    };
 +
 +    QQmlIncubator(IncubationMode = Asynchronous);
 +    virtual ~QQmlIncubator();
 +
 +    void clear();
 +    void forceCompletion();
 +
 +    bool isNull() const;
 +    bool isReady() const;
 +    bool isError() const;
 +    bool isLoading() const;
 +
 +    QList<QQmlError> errors() const;
 +
 +    IncubationMode incubationMode() const;
 +
 +    Status status() const;
 +
 +    QObject *object() const;
 +
 +protected:
 +    virtual void statusChanged(Status);
 +    virtual void setInitialState(QObject *);
 +
 +private:
 +    friend class QQmlComponent;
 +    friend class QQmlEnginePrivate;
 +    friend class QQmlIncubatorPrivate;
 +    QQmlIncubatorPrivate *d;
 +};
 +
 +class QQmlEnginePrivate;
 +class Q_QML_EXPORT QQmlIncubationController
 +{
 +    Q_DISABLE_COPY(QQmlIncubationController)
 +public:
 +    QQmlIncubationController();
 +    virtual ~QQmlIncubationController();
 +
 +    QQmlEngine *engine() const;
 +    int incubatingObjectCount() const;
 +
 +    void incubateFor(int msecs);
++    void incubateWhile(volatile bool *flag, int msecs=0);
 +
 +protected:
 +    virtual void incubatingObjectCountChanged(int);
 +
 +private:
 +    friend class QQmlEngine;
 +    friend class QQmlEnginePrivate;
 +    friend class QQmlIncubatorPrivate;
 +    QQmlEnginePrivate *d;
 +};
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QQMLINCUBATOR_H
index 72f04c9,0000000..b37117e
mode 100644,000000..100644
--- /dev/null
@@@ -1,278 -1,0 +1,278 @@@
-         qWarning().nospace() << idx << "\t\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlinstruction_p.h"
 +
 +#include "qqmlcompiler_p.h"
 +
 +#include <QtCore/qdebug.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +void QQmlCompiledData::dump(QQmlInstruction *instr, int idx)
 +{
 +#ifdef QT_NO_DEBUG_STREAM
 +    Q_UNUSED(instr)
 +    Q_UNUSED(idx)
 +#else
 +    switch (instructionType(instr)) {
 +    case QQmlInstruction::Init:
 +        qWarning().nospace() << idx << "\t\t" << "INIT\t\t\t" << instr->init.bindingsSize << "\t" << instr->init.parserStatusSize << "\t" << instr->init.contextCache << "\t" << instr->init.compiledBinding;
 +        break;
 +    case QQmlInstruction::DeferInit:
 +        qWarning().nospace() << idx << "\t\t" << "DEFER_INIT\t\t" << instr->deferInit.bindingsSize << "\t" << instr->deferInit.parserStatusSize;
 +        break;
 +    case QQmlInstruction::Done:
 +        qWarning().nospace() << idx << "\t\t" << "DONE";
 +        break;
 +    case QQmlInstruction::CreateCppObject:
 +        qWarning().nospace() << idx << "\t\t" << "CREATECPP\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className;
 +        break;
 +    case QQmlInstruction::CreateQMLObject:
 +        qWarning().nospace() << idx << "\t\t" << "CREATEQML\t\t\t" << instr->createQml.type << "\t" << instr->createQml.bindingBits << "\t\t" << types.at(instr->createQml.type).className;
 +        break;
 +    case QQmlInstruction::CompleteQMLObject:
 +        qWarning().nospace() << idx << "\t\t" << "COMPLETEQML";
 +        break;
 +    case QQmlInstruction::CreateSimpleObject:
 +        qWarning().nospace() << idx << "\t\t" << "CREATE_SIMPLE\t\t" << instr->createSimple.typeSize;
 +        break;
 +    case QQmlInstruction::SetId:
 +        qWarning().nospace() << idx << "\t\t" << "SETID\t\t\t" << instr->setId.value << "\t\t\t" << primitives.at(instr->setId.value);
 +        break;
 +    case QQmlInstruction::SetDefault:
 +        qWarning().nospace() << idx << "\t\t" << "SET_DEFAULT";
 +        break;
 +    case QQmlInstruction::CreateComponent:
 +        qWarning().nospace() << idx << "\t\t" << "CREATE_COMPONENT\t" << instr->createComponent.count;
 +        break;
 +    case QQmlInstruction::StoreMetaObject:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_META\t\t" << instr->storeMeta.data;
 +        break;
 +    case QQmlInstruction::StoreFloat:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value;
 +        break;
 +    case QQmlInstruction::StoreDouble:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value;
 +        break;
 +    case QQmlInstruction::StoreDoubleQList:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_DOUBLE_QLIST\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value;
 +        break;
 +    case QQmlInstruction::StoreInteger:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
 +        break;
 +    case QQmlInstruction::StoreIntegerQList:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_INTEGER_QLIST\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
 +        break;
 +    case QQmlInstruction::StoreBool:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
 +        break;
 +    case QQmlInstruction::StoreBoolQList:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_BOOL_QLIST\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
 +        break;
 +    case QQmlInstruction::StoreString:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
 +        break;
 +    case QQmlInstruction::StoreStringList:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_STRINGLIST\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
 +        break;
 +    case QQmlInstruction::StoreStringQList:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_STRING_QLIST\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
 +        break;
 +    case QQmlInstruction::StoreTrString:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_TR_STRING\t" << instr->storeTrString.propertyIndex << "\t" << instr->storeTrString.context << "\t" << instr->storeTrString.text << "\t" << instr->storeTrString.comment << "\t" << instr->storeTrString.n;
 +        break;
 +    case QQmlInstruction::StoreTrIdString:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_TRID_STRING\t" << instr->storeTrIdString.propertyIndex << "\t" << instr->storeTrIdString.text << "\t" << instr->storeTrIdString.n;
 +        break;
 +    case QQmlInstruction::StoreByteArray:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_BYTEARRAY" << instr->storeByteArray.propertyIndex << "\t" << instr->storeByteArray.value << "\t\t" << datas.at(instr->storeByteArray.value);
 +        break;
 +    case QQmlInstruction::StoreUrl:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_URL\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << urls.at(instr->storeUrl.value);
 +        break;
 +    case QQmlInstruction::StoreUrlQList:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_URL_QLIST\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << urls.at(instr->storeUrl.value);
 +        break;
 +    case QQmlInstruction::StoreColor:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t\t\t" << QString::number(instr->storeColor.value, 16);
 +        break;
 +    case QQmlInstruction::StoreDate:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value;
 +        break;
 +    case QQmlInstruction::StoreTime:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex;
 +        break;
 +    case QQmlInstruction::StoreDateTime:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex;
 +        break;
 +    case QQmlInstruction::StorePoint:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_POINT\t\t" << instr->storePoint.propertyIndex << "\t" << instr->storePoint.point.xp << "\t" << instr->storePoint.point.yp;
 +        break;
 +    case QQmlInstruction::StorePointF:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_POINTF\t\t" << instr->storePointF.propertyIndex << "\t" << instr->storePointF.point.xp << "\t" << instr->storePointF.point.yp;
 +        break;
 +    case QQmlInstruction::StoreSize:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_SIZE\t\t" << instr->storeSize.propertyIndex << "\t" << instr->storeSize.size.wd << "\t" << instr->storeSize.size.ht;
 +        break;
 +    case QQmlInstruction::StoreSizeF:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_SIZEF\t\t" << instr->storeSizeF.propertyIndex << "\t" << instr->storeSizeF.size.wd << "\t" << instr->storeSizeF.size.ht;
 +        break;
 +    case QQmlInstruction::StoreRect:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.rect.x1 << "\t" << instr->storeRect.rect.y1 << "\t" << instr->storeRect.rect.x2 << "\t" << instr->storeRect.rect.y2;
 +        break;
 +    case QQmlInstruction::StoreRectF:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_RECTF\t\t" << instr->storeRectF.propertyIndex << "\t" << instr->storeRectF.rect.xp << "\t" << instr->storeRectF.rect.yp << "\t" << instr->storeRectF.rect.w << "\t" << instr->storeRectF.rect.h;
 +        break;
 +    case QQmlInstruction::StoreVector3D:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR3D\t\t" << instr->storeVector3D.propertyIndex << "\t" << instr->storeVector3D.vector.xp << "\t" << instr->storeVector3D.vector.yp << "\t" << instr->storeVector3D.vector.zp;
 +        break;
 +    case QQmlInstruction::StoreVector4D:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_VECTOR4D\t\t" << instr->storeVector4D.propertyIndex << "\t" << instr->storeVector4D.vector.xp << "\t" << instr->storeVector4D.vector.yp << "\t" << instr->storeVector4D.vector.zp << "\t" << instr->storeVector4D.vector.wp;
 +        break;
 +    case QQmlInstruction::StoreVariant:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
 +        break;
 +    case QQmlInstruction::StoreVariantInteger:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
 +        break;
 +    case QQmlInstruction::StoreVariantDouble:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value;
 +        break;
 +    case QQmlInstruction::StoreVariantBool:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
 +        break;
 +    case QQmlInstruction::StoreObject:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex;
 +        break;
 +    case QQmlInstruction::StoreVariantObject:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_VARIANT_OBJECT\t" << instr->storeObject.propertyIndex;
 +        break;
 +    case QQmlInstruction::StoreInterface:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_INTERFACE\t\t" << instr->storeObject.propertyIndex;
 +        break;
 +    case QQmlInstruction::StoreSignal:
-         qWarning().nospace() << idx << "\t\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << primitives.at(instr->assignSignalObject.signal);
++        qWarning().nospace() << idx << "\t\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value;
 +        break;
 +    case QQmlInstruction::StoreImportedScript:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_IMPORTED_SCRIPT\t" << instr->storeScript.value;
 +        break;
 +    case QQmlInstruction::StoreScriptString:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_SCRIPT_STRING\t" << instr->storeScriptString.propertyIndex << "\t" << instr->storeScriptString.value << "\t" << instr->storeScriptString.scope << "\t" << instr->storeScriptString.bindingId;
 +        break;
 +    case QQmlInstruction::AssignSignalObject:
++        qWarning().nospace() << idx << "\t\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal;
 +        break;
 +    case QQmlInstruction::AssignCustomType:
 +        qWarning().nospace() << idx << "\t\t" << "ASSIGN_CUSTOMTYPE\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.primitive << "\t" << instr->assignCustomType.type;
 +        break;
 +    case QQmlInstruction::InitV8Bindings:
 +        qWarning().nospace() << idx << "\t\t" << "INIT_V8_BINDING\t" << instr->initV8Bindings.programIndex << "\t" << instr->initV8Bindings.line;
 +        break;
 +    case QQmlInstruction::StoreBinding:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_BINDING\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
 +        break;
 +    case QQmlInstruction::StoreBindingOnAlias:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_BINDING_ALIAS\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
 +        break;
 +    case QQmlInstruction::StoreV4Binding:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_COMPILED_BINDING\t" << instr->assignV4Binding.property << "\t" << instr->assignV4Binding.value << "\t" << instr->assignV4Binding.context;
 +        break;
 +    case QQmlInstruction::StoreV8Binding:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_V8_BINDING\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
 +        break;
 +    case QQmlInstruction::StoreValueSource:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property.coreIndex << "\t" << instr->assignValueSource.castValue;
 +        break;
 +    case QQmlInstruction::StoreValueInterceptor:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property.coreIndex << "\t" << instr->assignValueInterceptor.castValue;
 +        break;
 +    case QQmlInstruction::BeginObject:
 +        qWarning().nospace() << idx << "\t\t" << "BEGIN\t\t\t" << instr->begin.castValue;
 +        break;
 +    case QQmlInstruction::StoreObjectQList:
 +        qWarning().nospace() << idx << "\t\t" << "STORE_OBJECT_QLIST";
 +        break;
 +    case QQmlInstruction::AssignObjectList:
 +        qWarning().nospace() << idx << "\t\t" << "ASSIGN_OBJECT_LIST";
 +        break;
 +    case QQmlInstruction::FetchAttached:
 +        qWarning().nospace() << idx << "\t\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id;
 +        break;
 +    case QQmlInstruction::FetchQList:
 +        qWarning().nospace() << idx << "\t\t" << "FETCH_QLIST\t\t" << instr->fetch.property;
 +        break;
 +    case QQmlInstruction::FetchObject:
 +        qWarning().nospace() << idx << "\t\t" << "FETCH\t\t\t" << instr->fetch.property;
 +        break;
 +    case QQmlInstruction::FetchValueType:
 +        qWarning().nospace() << idx << "\t\t" << "FETCH_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type << "\t" << instr->fetchValue.bindingSkipList;
 +        break;
 +    case QQmlInstruction::PopFetchedObject:
 +        qWarning().nospace() << idx << "\t\t" << "POP";
 +        break;
 +    case QQmlInstruction::PopQList:
 +        qWarning().nospace() << idx << "\t\t" << "POP_QLIST";
 +        break;
 +    case QQmlInstruction::PopValueType:
 +        qWarning().nospace() << idx << "\t\t" << "POP_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type;
 +        break;
 +    case QQmlInstruction::Defer:
 +        qWarning().nospace() << idx << "\t\t" << "DEFER" << "\t\t\t" << instr->defer.deferCount;
 +        break;
 +    default:
 +        qWarning().nospace() << idx << "\t\t" << "XXX UNKNOWN INSTRUCTION" << "\t" << instructionType(instr);
 +        break;
 +    }
 +#endif // QT_NO_DEBUG_STREAM
 +}
 +
 +int QQmlInstruction::size(Type type)
 +{
 +#define QML_RETURN_INSTR_SIZE(I, FMT) case I: return QQmlInstructionMeta<(int)I>::Size;
 +    switch (type) {
 +    FOR_EACH_QML_INSTR(QML_RETURN_INSTR_SIZE)
 +    default: return 0;
 +    }
 +#undef QML_RETURN_INSTR_SIZE
 +}
 +
 +QT_END_NAMESPACE
index 4dc30f2,0000000..d684378
mode 100644,000000..100644
--- /dev/null
@@@ -1,1123 -1,0 +1,1126 @@@
-     return v8::Integer::New(r->locale.firstDayOfWeek());
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmllocale_p.h"
 +#include "qqmlengine_p.h"
 +#include <private/qqmlcontext_p.h>
 +#include <private/qjsconverter_impl_p.h>
 +#include <QtCore/qnumeric.h>
 +#include <QtCore/qdatetime.h>
 +
 +#include <private/qlocale_p.h>
 +#include <private/qlocale_data_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QV8LocaleDataResource : public QV8ObjectResource
 +{
 +    V8_RESOURCE_TYPE(LocaleDataType)
 +public:
 +    QV8LocaleDataResource(QV8Engine *e) : QV8ObjectResource(e) {}
 +    QLocale locale;
 +};
 +
 +#define GET_LOCALE_DATA_RESOURCE(OBJECT) \
 +QV8LocaleDataResource *r = v8_resource_cast<QV8LocaleDataResource>(OBJECT); \
 +if (!r) \
 +    V8THROW_ERROR("Not a valid Locale object")
 +
 +static bool isLocaleObject(v8::Handle<v8::Value> val)
 +{
 +    if (!val->IsObject())
 +        return false;
 +
 +    v8::Handle<v8::Object> localeObj = val->ToObject();
 +    return localeObj->Has(v8::String::New("nativeLanguageName")); //XXX detect locale object properly
 +}
 +
 +//--------------
 +// Date extension
 +
 +static const char *dateToLocaleStringFunction =
 +        "(function(toLocaleStringFunc) { "
 +        "  var orig_toLocaleString;"
 +        "  orig_toLocaleString = Date.prototype.toLocaleString;"
 +        "  Date.prototype.toLocaleString = (function() {"
 +        "    var val = toLocaleStringFunc.apply(this, arguments);"
 +        "    if (val == undefined) val = orig_toLocaleString.call(this);"
 +        "    return val;"
 +        "  })"
 +        "})";
 +
 +static const char *dateToLocaleTimeStringFunction =
 +        "(function(toLocaleTimeStringFunc) { "
 +        "  var orig_toLocaleTimeString;"
 +        "  orig_toLocaleTimeString = Date.prototype.toLocaleTimeString;"
 +        "  Date.prototype.toLocaleTimeString = (function() {"
 +        "    var val = toLocaleTimeStringFunc.apply(this, arguments);"
 +        "    if (val == undefined) val = orig_toLocaleTimeString.call(this);"
 +        "    return val;"
 +        "  })"
 +        "})";
 +
 +static const char *dateToLocaleDateStringFunction =
 +        "(function(toLocaleDateStringFunc) { "
 +        "  var orig_toLocaleDateString;"
 +        "  orig_toLocaleDateString = Date.prototype.toLocaleDateString;"
 +        "  Date.prototype.toLocaleDateString = (function() {"
 +        "    var val = toLocaleDateStringFunc.apply(this, arguments);"
 +        "    if (val == undefined) val = orig_toLocaleDateString.call(this);"
 +        "    return val;"
 +        "  })"
 +        "})";
 +
 +
 +static const char *dateFromLocaleStringFunction =
 +        "(function(fromLocaleStringFunc) { "
 +        "  Date.fromLocaleString = (function() {"
 +        "    return fromLocaleStringFunc.apply(null, arguments);"
 +        "  })"
 +        "})";
 +
 +static const char *dateFromLocaleTimeStringFunction =
 +        "(function(fromLocaleTimeStringFunc) { "
 +        "  Date.fromLocaleTimeString = (function() {"
 +        "    return fromLocaleTimeStringFunc.apply(null, arguments);"
 +        "  })"
 +        "})";
 +
 +static const char *dateFromLocaleDateStringFunction =
 +        "(function(fromLocaleDateStringFunc) { "
 +        "  Date.fromLocaleDateString = (function() {"
 +        "    return fromLocaleDateStringFunc.apply(null, arguments);"
 +        "  })"
 +        "})";
 +
 +
 +static void registerFunction(QV8Engine *engine, const char *script, v8::InvocationCallback func)
 +{
 +    v8::Local<v8::Script> registerScript = v8::Script::New(v8::String::New(script), 0, 0, v8::Handle<v8::String>(), v8::Script::NativeMode);
 +    v8::Local<v8::Value> result = registerScript->Run();
 +    Q_ASSERT(result->IsFunction());
 +    v8::Local<v8::Function> registerFunc = v8::Local<v8::Function>::Cast(result);
 +    v8::Handle<v8::Value> args = V8FUNCTION(func, engine);
 +    registerFunc->Call(v8::Local<v8::Object>::Cast(registerFunc), 1, &args);
 +}
 +
 +void QQmlDateExtension::registerExtension(QV8Engine *engine)
 +{
 +    registerFunction(engine, dateToLocaleStringFunction, toLocaleString);
 +    registerFunction(engine, dateToLocaleTimeStringFunction, toLocaleTimeString);
 +    registerFunction(engine, dateToLocaleDateStringFunction, toLocaleDateString);
 +    registerFunction(engine, dateFromLocaleStringFunction, fromLocaleString);
 +    registerFunction(engine, dateFromLocaleTimeStringFunction, fromLocaleTimeString);
 +    registerFunction(engine, dateFromLocaleDateStringFunction, fromLocaleDateString);
 +}
 +
 +v8::Handle<v8::Value> QQmlDateExtension::toLocaleString(const v8::Arguments& args)
 +{
 +    if (args.Length() > 2)
 +        return v8::Undefined();
 +
 +    if (!args.This()->IsDate())
 +        return v8::Undefined();
 +
 +    QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
 +
 +    if (args.Length() == 0) {
 +        // Use QLocale for standard toLocaleString() function
 +        QLocale locale;
 +        return QJSConverter::toString(locale.toString(dt));
 +    }
 +
 +    if (!isLocaleObject(args[0]))
 +        return v8::Undefined(); // Use the default Date toLocaleString()
 +
 +    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
 +
 +    QLocale::FormatType enumFormat = QLocale::LongFormat;
 +    QString formattedDt;
 +    if (args.Length() == 2) {
 +        if (args[1]->IsString()) {
 +            QString format = r->engine->toVariant(args[1], -1).toString();
 +            formattedDt = r->locale.toString(dt, format);
 +        } else if (args[1]->IsNumber()) {
 +            quint32 intFormat = args[1]->ToNumber()->Value();
 +            QLocale::FormatType format = QLocale::FormatType(intFormat);
 +            formattedDt = r->locale.toString(dt, format);
 +        } else {
 +            V8THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format");
 +        }
 +    } else {
 +         formattedDt = r->locale.toString(dt, enumFormat);
 +    }
 +
 +    return r->engine->toString(formattedDt);
 +}
 +
 +v8::Handle<v8::Value> QQmlDateExtension::toLocaleTimeString(const v8::Arguments& args)
 +{
 +    if (args.Length() > 2)
 +        return v8::Undefined();
 +
 +    if (!args.This()->IsDate())
 +        return v8::Undefined();
 +
 +    QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
 +    QTime time = dt.time();
 +
 +    if (args.Length() == 0) {
 +        // Use QLocale for standard toLocaleString() function
 +        QLocale locale;
 +        return QJSConverter::toString(locale.toString(time));
 +    }
 +
 +    if (!isLocaleObject(args[0]))
 +        return v8::Undefined(); // Use the default Date toLocaleTimeString()
 +
 +    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
 +
 +    QLocale::FormatType enumFormat = QLocale::LongFormat;
 +    QString formattedTime;
 +    if (args.Length() == 2) {
 +        if (args[1]->IsString()) {
 +            QString format = r->engine->toVariant(args[1], -1).toString();
 +            formattedTime = r->locale.toString(time, format);
 +        } else if (args[1]->IsNumber()) {
 +            quint32 intFormat = args[1]->ToNumber()->Value();
 +            QLocale::FormatType format = QLocale::FormatType(intFormat);
 +            formattedTime = r->locale.toString(time, format);
 +        } else {
 +            V8THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format");
 +        }
 +    } else {
 +         formattedTime = r->locale.toString(time, enumFormat);
 +    }
 +
 +    return r->engine->toString(formattedTime);
 +}
 +
 +v8::Handle<v8::Value> QQmlDateExtension::toLocaleDateString(const v8::Arguments& args)
 +{
 +    if (args.Length() > 2)
 +        return v8::Undefined();
 +
 +    if (!args.This()->IsDate())
 +        return v8::Undefined();
 +
 +    QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
 +    QDate date = dt.date();
 +
 +    if (args.Length() == 0) {
 +        // Use QLocale for standard toLocaleString() function
 +        QLocale locale;
 +        return QJSConverter::toString(locale.toString(date));
 +    }
 +
 +    if (!isLocaleObject(args[0]))
 +        return v8::Undefined(); // Use the default Date toLocaleDateString()
 +
 +    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
 +
 +    QLocale::FormatType enumFormat = QLocale::LongFormat;
 +    QString formattedDate;
 +    if (args.Length() == 2) {
 +        if (args[1]->IsString()) {
 +            QString format = r->engine->toVariant(args[1], -1).toString();
 +            formattedDate = r->locale.toString(date, format);
 +        } else if (args[1]->IsNumber()) {
 +            quint32 intFormat = args[1]->ToNumber()->Value();
 +            QLocale::FormatType format = QLocale::FormatType(intFormat);
 +            formattedDate = r->locale.toString(date, format);
 +        } else {
 +            V8THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format");
 +        }
 +    } else {
 +         formattedDate = r->locale.toString(date, enumFormat);
 +    }
 +
 +    return r->engine->toString(formattedDate);
 +}
 +
 +v8::Handle<v8::Value> QQmlDateExtension::fromLocaleString(const v8::Arguments& args)
 +{
 +    if (args.Length() == 1 && args[0]->IsString()) {
 +        QLocale locale;
 +        QString dateString = QJSConverter::toString(args[0]->ToString());
 +        QDateTime dt = locale.toDateTime(dateString);
 +        return QJSConverter::toDateTime(dt);
 +    }
 +
 +    if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
 +        V8THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments");
 +
 +    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
 +
 +    QLocale::FormatType enumFormat = QLocale::LongFormat;
 +    QDateTime dt;
 +    QString dateString = r->engine->toString(args[1]->ToString());
 +    if (args.Length() == 3) {
 +        if (args[2]->IsString()) {
 +            QString format = r->engine->toString(args[2]->ToString());
 +            dt = r->locale.toDateTime(dateString, format);
 +        } else if (args[2]->IsNumber()) {
 +            quint32 intFormat = args[2]->ToNumber()->Value();
 +            QLocale::FormatType format = QLocale::FormatType(intFormat);
 +            dt = r->locale.toDateTime(dateString, format);
 +        } else {
 +            V8THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format");
 +        }
 +    } else {
 +        dt = r->locale.toDateTime(dateString, enumFormat);
 +    }
 +
 +    return QJSConverter::toDateTime(dt);
 +}
 +
 +v8::Handle<v8::Value> QQmlDateExtension::fromLocaleTimeString(const v8::Arguments& args)
 +{
 +    if (args.Length() == 1 && args[0]->IsString()) {
 +        QLocale locale;
 +        QString timeString = QJSConverter::toString(args[0]->ToString());
 +        QTime time = locale.toTime(timeString);
 +        QDateTime dt = QDateTime::currentDateTime();
 +        dt.setTime(time);
 +        return QJSConverter::toDateTime(dt);
 +    }
 +
 +    if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
 +        V8THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments");
 +
 +    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
 +
 +    QLocale::FormatType enumFormat = QLocale::LongFormat;
 +    QTime tm;
 +    QString dateString = r->engine->toString(args[1]->ToString());
 +    if (args.Length() == 3) {
 +        if (args[2]->IsString()) {
 +            QString format = r->engine->toString(args[2]->ToString());
 +            tm = r->locale.toTime(dateString, format);
 +        } else if (args[2]->IsNumber()) {
 +            quint32 intFormat = args[2]->ToNumber()->Value();
 +            QLocale::FormatType format = QLocale::FormatType(intFormat);
 +            tm = r->locale.toTime(dateString, format);
 +        } else {
 +            V8THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format");
 +        }
 +    } else {
 +        tm = r->locale.toTime(dateString, enumFormat);
 +    }
 +
 +    QDateTime dt = QDateTime::currentDateTime();
 +    dt.setTime(tm);
 +
 +    return QJSConverter::toDateTime(dt);
 +}
 +
 +v8::Handle<v8::Value> QQmlDateExtension::fromLocaleDateString(const v8::Arguments& args)
 +{
 +    if (args.Length() == 1 && args[0]->IsString()) {
 +        QLocale locale;
 +        QString dateString = QJSConverter::toString(args[0]->ToString());
 +        QDate date = locale.toDate(dateString);
 +        return QJSConverter::toDateTime(QDateTime(date));
 +    }
 +
 +    if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
 +        V8THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments");
 +
 +    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
 +
 +    QLocale::FormatType enumFormat = QLocale::LongFormat;
 +    QDate dt;
 +    QString dateString = r->engine->toString(args[1]->ToString());
 +    if (args.Length() == 3) {
 +        if (args[2]->IsString()) {
 +            QString format = r->engine->toString(args[2]->ToString());
 +            dt = r->locale.toDate(dateString, format);
 +        } else if (args[2]->IsNumber()) {
 +            quint32 intFormat = args[2]->ToNumber()->Value();
 +            QLocale::FormatType format = QLocale::FormatType(intFormat);
 +            dt = r->locale.toDate(dateString, format);
 +        } else {
 +            V8THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format");
 +        }
 +    } else {
 +        dt = r->locale.toDate(dateString, enumFormat);
 +    }
 +
 +    return QJSConverter::toDateTime(QDateTime(dt));
 +}
 +
 +//-----------------
 +// Number extension
 +
 +static const char *numberToLocaleStringFunction =
 +        "(function(toLocaleStringFunc) { "
 +        "  var orig_toLocaleString;"
 +        "  orig_toLocaleString = Number.prototype.toLocaleString;"
 +        "  Number.prototype.toLocaleString = (function() {"
 +        "    var val = toLocaleStringFunc.apply(this, arguments);"
 +        "    if (val == undefined) val = orig_toLocaleString.call(this);"
 +        "    return val;"
 +        "  })"
 +        "})";
 +
 +static const char *numberToLocaleCurrencyStringFunction =
 +        "(function(toLocaleCurrencyStringFunc) { "
 +        "  Number.prototype.toLocaleCurrencyString = (function() {"
 +        "    return toLocaleCurrencyStringFunc.apply(this, arguments);"
 +        "  })"
 +        "})";
 +
 +static const char *numberFromLocaleStringFunction =
 +        "(function(fromLocaleStringFunc) { "
 +        "  Number.fromLocaleString = (function() {"
 +        "    return fromLocaleStringFunc.apply(null, arguments);"
 +        "  })"
 +        "})";
 +
 +
 +void QQmlNumberExtension::registerExtension(QV8Engine *engine)
 +{
 +    registerFunction(engine, numberToLocaleStringFunction, toLocaleString);
 +    registerFunction(engine, numberToLocaleCurrencyStringFunction, toLocaleCurrencyString);
 +    registerFunction(engine, numberFromLocaleStringFunction, fromLocaleString);
 +}
 +
 +v8::Handle<v8::Value> QQmlNumberExtension::toLocaleString(const v8::Arguments& args)
 +{
 +    if (args.Length() > 3)
 +        V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
 +
 +    double number = args.This()->ToNumber()->Value();
 +
 +    if (args.Length() == 0) {
 +        // Use QLocale for standard toLocaleString() function
 +        QLocale locale;
 +        return QJSConverter::toString(locale.toString(number));
 +    }
 +
 +    if (!isLocaleObject(args[0]))
 +        return v8::Undefined(); // Use the default Number toLocaleString()
 +
 +    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
 +
 +    uint16_t format = 'f';
 +    if (args.Length() > 1) {
 +        if (!args[1]->IsString())
 +            V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
 +        v8::Local<v8::String> fs = args[1]->ToString();
 +        if (!fs.IsEmpty() && fs->Length())
 +            format = fs->GetCharacter(0);
 +    }
 +    int prec = 2;
 +    if (args.Length() > 2) {
 +        if (!args[2]->IsNumber())
 +            V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
 +         prec = args[2]->IntegerValue();
 +    }
 +
 +    return r->engine->toString(r->locale.toString(number, (char)format, prec));
 +}
 +
 +v8::Handle<v8::Value> QQmlNumberExtension::toLocaleCurrencyString(const v8::Arguments& args)
 +{
 +    if (args.Length() > 2)
 +        V8THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
 +
 +    double number = args.This()->ToNumber()->Value();
 +
 +    if (args.Length() == 0) {
 +        // Use QLocale for standard toLocaleString() function
 +        QLocale locale;
 +        return QJSConverter::toString(locale.toString(number));
 +    }
 +
 +    if (!isLocaleObject(args[0]))
 +        V8THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
 +
 +    GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
 +
 +    QString symbol;
 +    if (args.Length() > 1) {
 +        if (!args[1]->IsString())
 +            V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
 +        symbol = r->engine->toString(args[1]->ToString());
 +    }
 +
 +    return r->engine->toString(r->locale.toCurrencyString(number, symbol));
 +}
 +
 +v8::Handle<v8::Value> QQmlNumberExtension::fromLocaleString(const v8::Arguments& args)
 +{
 +    if (args.Length() < 1 || args.Length() > 2)
 +        V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
 +
 +    int numberIdx = 0;
 +    QLocale locale;
 +
 +    if (args.Length() == 2) {
 +        if (!isLocaleObject(args[0]))
 +            V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
 +
 +        GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
 +        locale = r->locale;
 +
 +        numberIdx = 1;
 +    }
 +
 +    v8::Local<v8::String> ns = args[numberIdx]->ToString();
 +    if (ns.IsEmpty() || ns->Length() == 0)
 +        return v8::Number::New(Q_QNAN);
 +
 +    bool ok = false;
 +    double val = locale.toDouble(QJSConverter::toString(ns), &ok);
 +
 +    if (!ok)
 +        V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format")
 +
 +    return v8::Number::New(val);
 +}
 +
 +//--------------
 +// Locale object
 +
 +static v8::Handle<v8::Value> locale_get_firstDayOfWeek(v8::Local<v8::String>, const v8::AccessorInfo &info)
 +{
 +    GET_LOCALE_DATA_RESOURCE(info.This());
++    int fdow = int(r->locale.firstDayOfWeek());
++    if (fdow == 7)
++        fdow = 0; // Qt::Sunday = 7, but Sunday is 0 in JS Date
++    return v8::Integer::New(fdow);
 +}
 +
 +static v8::Handle<v8::Value> locale_get_measurementSystem(v8::Local<v8::String>, const v8::AccessorInfo &info)
 +{
 +    GET_LOCALE_DATA_RESOURCE(info.This());
 +    return v8::Integer::New(r->locale.measurementSystem());
 +}
 +
 +static v8::Handle<v8::Value> locale_get_textDirection(v8::Local<v8::String>, const v8::AccessorInfo &info)
 +{
 +    GET_LOCALE_DATA_RESOURCE(info.This());
 +    return v8::Integer::New(r->locale.textDirection());
 +}
 +
 +static v8::Handle<v8::Value> locale_get_weekDays(v8::Local<v8::String>, const v8::AccessorInfo &info)
 +{
 +    GET_LOCALE_DATA_RESOURCE(info.This());
 +
 +    QList<Qt::DayOfWeek> days = r->locale.weekdays();
 +
 +    v8::Handle<v8::Array> result = v8::Array::New(days.size());
 +    for (int i = 0; i < days.size(); ++i) {
 +        int day = days.at(i);
 +        if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
 +            day = 0;
 +        result->Set(i, v8::Integer::New(day));
 +    }
 +
 +    return result;
 +}
 +
 +static v8::Handle<v8::Value> locale_get_uiLanguages(v8::Local<v8::String>, const v8::AccessorInfo &info)
 +{
 +    GET_LOCALE_DATA_RESOURCE(info.This());
 +
 +    QStringList langs = r->locale.uiLanguages();
 +    v8::Handle<v8::Array> result = v8::Array::New(langs.size());
 +    for (int i = 0; i < langs.size(); ++i) {
 +        result->Set(i, r->engine->toString(langs.at(i)));
 +    }
 +
 +    return result;
 +}
 +
 +static v8::Handle<v8::Value> locale_currencySymbol(const v8::Arguments &args)
 +{
 +    GET_LOCALE_DATA_RESOURCE(args.This());
 +
 +    if (args.Length() > 1)
 +        V8THROW_ERROR("Locale: currencySymbol(): Invalid arguments");
 +
 +    QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol;
 +    if (args.Length() == 1) {
 +        quint32 intFormat = args[0]->ToNumber()->Value();
 +        format = QLocale::CurrencySymbolFormat(intFormat);
 +    }
 +
 +    return r->engine->toString(r->locale.currencySymbol(format));
 +}
 +
 +#define LOCALE_FORMAT(FUNC) \
 +static v8::Handle<v8::Value> locale_ ##FUNC (const v8::Arguments &args) { \
 +    GET_LOCALE_DATA_RESOURCE(args.This());\
 +    if (args.Length() > 1) \
 +        V8THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \
 +    QLocale::FormatType format = QLocale::LongFormat;\
 +    if (args.Length() == 1) { \
 +        quint32 intFormat = args[0]->Uint32Value(); \
 +        format = QLocale::FormatType(intFormat); \
 +    } \
 +    return r->engine->toString(r->locale. FUNC (format)); \
 +}
 +
 +LOCALE_FORMAT(dateTimeFormat)
 +LOCALE_FORMAT(timeFormat)
 +LOCALE_FORMAT(dateFormat)
 +
 +// +1 added to idx because JS is 0-based, whereas QLocale months begin at 1.
 +#define LOCALE_FORMATTED_MONTHNAME(VARIABLE) \
 +static v8::Handle<v8::Value> locale_ ## VARIABLE (const v8::Arguments &args) {\
 +    GET_LOCALE_DATA_RESOURCE(args.This()); \
 +    if (args.Length() < 1 || args.Length() > 2) \
 +        V8THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
 +    QLocale::FormatType enumFormat = QLocale::LongFormat; \
 +    int idx = args[0]->IntegerValue() + 1; \
 +    if (idx < 1 || idx > 12) \
 +        V8THROW_ERROR("Locale: Invalid month"); \
 +    QString name; \
 +    if (args.Length() == 2) { \
 +        if (args[1]->IsNumber()) { \
 +            quint32 intFormat = args[1]->IntegerValue(); \
 +            QLocale::FormatType format = QLocale::FormatType(intFormat); \
 +            name = r->locale. VARIABLE(idx, format); \
 +        } else { \
 +            V8THROW_ERROR("Locale: Invalid datetime format"); \
 +        } \
 +    } else { \
 +        name = r->locale. VARIABLE(idx, enumFormat); \
 +    } \
 +    return r->engine->toString(name); \
 +}
 +
 +// 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date
 +#define LOCALE_FORMATTED_DAYNAME(VARIABLE) \
 +static v8::Handle<v8::Value> locale_ ## VARIABLE (const v8::Arguments &args) {\
 +    GET_LOCALE_DATA_RESOURCE(args.This()); \
 +    if (args.Length() < 1 || args.Length() > 2) \
 +        V8THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
 +    QLocale::FormatType enumFormat = QLocale::LongFormat; \
 +    int idx = args[0]->IntegerValue(); \
 +    if (idx < 0 || idx > 7) \
 +        V8THROW_ERROR("Locale: Invalid day"); \
 +    if (idx == 0) idx = 7; \
 +    QString name; \
 +    if (args.Length() == 2) { \
 +        if (args[1]->IsNumber()) { \
 +            quint32 intFormat = args[1]->ToNumber()->Value(); \
 +            QLocale::FormatType format = QLocale::FormatType(intFormat); \
 +            name = r->locale. VARIABLE(idx, format); \
 +        } else { \
 +            V8THROW_ERROR("Locale: Invalid datetime format"); \
 +        } \
 +    } else { \
 +        name = r->locale. VARIABLE(idx, enumFormat); \
 +    } \
 +    return r->engine->toString(name); \
 +}
 +
 +
 +#define LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(FT, VARIABLE, ENGINE) \
 +    FT->PrototypeTemplate()->Set(v8::String::New( #VARIABLE ), V8FUNCTION(locale_ ## VARIABLE, ENGINE));
 +
 +LOCALE_FORMATTED_MONTHNAME(monthName)
 +LOCALE_FORMATTED_MONTHNAME(standaloneMonthName)
 +LOCALE_FORMATTED_DAYNAME(dayName)
 +LOCALE_FORMATTED_DAYNAME(standaloneDayName)
 +
 +#define LOCALE_STRING_PROPERTY(VARIABLE) static v8::Handle<v8::Value> locale_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
 +{ \
 +    GET_LOCALE_DATA_RESOURCE(info.This()); \
 +    return r->engine->toString(r->locale. VARIABLE());\
 +}
 +
 +#define LOCALE_REGISTER_STRING_ACCESSOR(FT, VARIABLE) \
 +    FT ->PrototypeTemplate()->SetAccessor( v8::String::New( #VARIABLE ), locale_get_ ## VARIABLE )
 +
 +
 +LOCALE_STRING_PROPERTY(name)
 +LOCALE_STRING_PROPERTY(nativeLanguageName)
 +LOCALE_STRING_PROPERTY(nativeCountryName)
 +LOCALE_STRING_PROPERTY(decimalPoint)
 +LOCALE_STRING_PROPERTY(groupSeparator)
 +LOCALE_STRING_PROPERTY(percent)
 +LOCALE_STRING_PROPERTY(zeroDigit)
 +LOCALE_STRING_PROPERTY(negativeSign)
 +LOCALE_STRING_PROPERTY(positiveSign)
 +LOCALE_STRING_PROPERTY(exponential)
 +LOCALE_STRING_PROPERTY(amText)
 +LOCALE_STRING_PROPERTY(pmText)
 +
 +class QV8LocaleDataDeletable : public QV8Engine::Deletable
 +{
 +public:
 +    QV8LocaleDataDeletable(QV8Engine *engine);
 +    ~QV8LocaleDataDeletable();
 +
 +    v8::Persistent<v8::Function> constructor;
 +};
 +
 +QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine)
 +{
 +    v8::HandleScope handle_scope;
 +    v8::Context::Scope scope(engine->context());
 +
 +    v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
 +    ft->InstanceTemplate()->SetHasExternalResource(true);
 +
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, name);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, nativeLanguageName);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, nativeCountryName);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, decimalPoint);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, groupSeparator);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, percent);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, zeroDigit);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, negativeSign);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, positiveSign);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, exponential);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, amText);
 +    LOCALE_REGISTER_STRING_ACCESSOR(ft, pmText);
 +
 +    ft->PrototypeTemplate()->Set(v8::String::New("currencySymbol"), V8FUNCTION(locale_currencySymbol, engine));
 +
 +    ft->PrototypeTemplate()->Set(v8::String::New("dateTimeFormat"), V8FUNCTION(locale_dateTimeFormat, engine));
 +    ft->PrototypeTemplate()->Set(v8::String::New("dateFormat"), V8FUNCTION(locale_dateFormat, engine));
 +    ft->PrototypeTemplate()->Set(v8::String::New("timeFormat"), V8FUNCTION(locale_timeFormat, engine));
 +
 +    LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, monthName, engine);
 +    LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, standaloneMonthName, engine);
 +    LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, dayName, engine);
 +    LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, standaloneDayName, engine);
 +
 +    ft->PrototypeTemplate()->SetAccessor(v8::String::New("firstDayOfWeek"), locale_get_firstDayOfWeek);
 +    ft->PrototypeTemplate()->SetAccessor(v8::String::New("weekDays"), locale_get_weekDays);
 +    ft->PrototypeTemplate()->SetAccessor(v8::String::New("measurementSystem"), locale_get_measurementSystem);
 +    ft->PrototypeTemplate()->SetAccessor(v8::String::New("textDirection"), locale_get_textDirection);
 +    ft->PrototypeTemplate()->SetAccessor(v8::String::New("uiLanguages"), locale_get_uiLanguages);
 +
 +    constructor = qPersistentNew(ft->GetFunction());
 +}
 +
 +QV8LocaleDataDeletable::~QV8LocaleDataDeletable()
 +{
 +    qPersistentDispose(constructor);
 +}
 +
 +V8_DEFINE_EXTENSION(QV8LocaleDataDeletable, localeV8Data);
 +
 +/*!
 +    \qmlclass Locale QQmlLocale
 +    \inqmlmodule QtQuick 2
 +    \brief The Locale object provides locale specific properties and formatted data.
 +
 +    The Locale object is created via the \l{QML:Qt::locale()}{Qt.locale()} function.  It cannot be created
 +    directly.
 +
 +    The \l{QML:Qt::locale()}{Qt.locale()} function returns a JS Locale object representing the
 +    locale with the specified name, which has the format
 +    "language[_territory][.codeset][@modifier]" or "C".
 +
 +    Locale supports the concept of a default locale, which is
 +    determined from the system's locale settings at application
 +    startup.  If no parameter is passed to Qt.locale() the default
 +    locale object is returned.
 +
 +    The Locale object provides a number of functions and properties
 +    providing data for the specified locale.
 +
 +    The Locale object may also be passed to the \l Date and \l Number toLocaleString()
 +    and fromLocaleString() methods in order to convert to/from strings using
 +    the specified locale.
 +
 +    This example shows the current date formatted for the German locale:
 +
 +    \code
 +    import QtQuick 2.0
 +
 +    Text {
 +        text: "The date is: " + Date().toLocaleString(Qt.locale("de_DE"))
 +    }
 +    \endcode
 +
 +    The following example displays the specified number
 +    in the correct format for the default locale:
 +
 +    \code
 +    import QtQuick 2.0
 +
 +    Text {
 +        text: "The value is: " + Number(23443.34).toLocaleString(Qt.locale())
 +    }
 +    \endcode
 +
 +    QtQuick Locale's data is based on Common Locale Data Repository v1.8.1.
 +
 +    The double-to-string and string-to-double conversion functions are
 +    covered by the following licenses:
 +
 +    \legalese
 +    Copyright (c) 1991 by AT&T.
 +
 +    Permission to use, copy, modify, and distribute this software for any
 +    purpose without fee is hereby granted, provided that this entire notice
 +    is included in all copies of any software which is or includes a copy
 +    or modification of this software and in all copies of the supporting
 +    documentation for such software.
 +
 +    THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
 +    WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
 +    REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
 +    OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
 +
 +    This product includes software developed by the University of
 +    California, Berkeley and its contributors.
 +
 +    \sa {QtQuick2::Date}{Date} {QtQuick2::Number}{Number}
 +*/
 +
 +QQmlLocale::QQmlLocale()
 +{
 +}
 +
 +QQmlLocale::~QQmlLocale()
 +{
 +}
 +
 +v8::Handle<v8::Value> QQmlLocale::locale(QV8Engine *v8engine, const QString &locale)
 +{
 +    QV8LocaleDataDeletable *d = localeV8Data(v8engine);
 +    v8::Local<v8::Object> v8Value = d->constructor->NewInstance();
 +    QV8LocaleDataResource *r = new QV8LocaleDataResource(v8engine);
 +    if (locale.isEmpty())
 +        r->locale = QLocale();
 +    else
 +        r->locale = QLocale(locale);
 +    v8Value->SetExternalResource(r);
 +
 +    return v8Value;
 +}
 +
 +static const char *localeCompareFunction =
 +    "(function(localeCompareFunc) { "
 +    "  var orig_localeCompare;"
 +    "  orig_localeCompare = String.prototype.localeCompare;"
 +    "  String.prototype.localeCompare = (function() {"
 +    "    var val = localeCompareFunc.apply(this, arguments);"
 +    "    if (val == undefined) val = orig_localeCompare.call(this);"
 +    "    return val;"
 +    "  })"
 +    "})";
 +
 +void QQmlLocale::registerStringLocaleCompare(QV8Engine *engine)
 +{
 +    registerFunction(engine, localeCompareFunction, localeCompare);
 +}
 +
 +v8::Handle<v8::Value> QQmlLocale::localeCompare(const v8::Arguments &args)
 +{
 +    if (args.Length() != 1 || (!args[0]->IsString() && !args[0]->IsStringObject()))
 +        return v8::Undefined();
 +
 +    if (!args.This()->IsString() && !args.This()->IsStringObject())
 +        return v8::Undefined();
 +
 +    QString thisString = QJSConverter::toString(args.This()->ToString());
 +    QString thatString = QJSConverter::toString(args[0]->ToString());
 +
 +    return v8::Integer::New(QString::localeAwareCompare(thisString, thatString));
 +}
 +
 +/*!
 +    \enum QtQuick2::Locale::FormatType
 +
 +    This enumeration describes the types of format that can be used when
 +    converting Date objects to strings.
 +
 +    \value LongFormat The long version of day and month names; for
 +    example, returning "January" as a month name.
 +
 +    \value ShortFormat The short version of day and month names; for
 +    example, returning "Jan" as a month name.
 +
 +    \value NarrowFormat A special version of day and month names for
 +    use when space is limited; for example, returning "J" as a month
 +    name. Note that the narrow format might contain the same text for
 +    different months and days or it can even be an empty string if the
 +    locale doesn't support narrow names, so you should avoid using it
 +    for date formatting. Also, for the system locale this format is
 +    the same as ShortFormat.
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::name
 +
 +    Holds the language and country of this locale as a
 +    string of the form "language_country", where
 +    language is a lowercase, two-letter ISO 639 language code,
 +    and country is an uppercase, two- or three-letter ISO 3166 country code.
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::decimalPoint
 +
 +    Holds the decimal point character of this locale.
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::groupSeparator
 +
 +    Holds the group separator character of this locale.
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::percent
 +
 +    Holds the percent character of this locale.
 +*/
 +
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::zeroDigit
 +
 +    Holds Returns the zero digit character of this locale.
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::negativeSign
 +
 +    Holds the negative sign character of this locale.
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::positiveSign
 +
 +    Holds the positive sign character of this locale.
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::exponential
 +
 +    Holds the exponential character of this locale.
 +*/
 +
 +/*!
 +    \qmlmethod string QtQuick2::Locale::dateTimeFormat(type)
 +
 +    Returns the date time format used for the current locale.
 +    \a type specifies the FormatType to return.
 +
 +    \sa {QtQuick2::Date}{Date}
 +*/
 +
 +/*!
 +    \qmlmethod string QtQuick2::Locale::dateFormat(type)
 +
 +    Returns the date format used for the current locale.
 +    \a type specifies the FormatType to return.
 +
 +    \sa {QtQuick2::Date}{Date}
 +*/
 +
 +/*!
 +    \qmlmethod string QtQuick2::Locale::timeFormat(type)
 +
 +    Returns the time format used for the current locale.
 +    \a type specifies the FormatType to return.
 +
 +    \sa {QtQuick2::Date}{Date}
 +*/
 +
 +/*!
 +    \qmlmethod string QtQuick2::Locale::monthName(month, type)
 +
 +    Returns the localized name of \a month (0-11), in the optional
 +    \l FortmatType specified by \a type.
 +
 +    \note the QLocale C++ API expects a range of (1-12), however Locale.monthName()
 +    expects 0-11 as per the JS Date object.
 +
 +    \sa dayName(), standaloneMonthName()
 +*/
 +
 +/*!
 +    \qmlmethod string QtQuick2::Locale::standaloneMonthName(month, type)
 +
 +    Returns the localized name of \a month (0-11) that is used as a
 +    standalone text, in the optional \l FormatType specified by \a type.
 +
 +    If the locale information doesn't specify the standalone month
 +    name then return value is the same as in monthName().
 +
 +    \note the QLocale C++ API expects a range of (1-12), however Locale.standaloneMonthName()
 +    expects 0-11 as per the JS Date object.
 +
 +    \sa monthName(), standaloneDayName()
 +*/
 +
 +/*!
 +    \qmlmethod string QtQuick2::Locale::dayName(day, type)
 +
 +    Returns the localized name of the \a day (where 0 represents
 +    Sunday, 1 represents Monday and so on), in the optional
 +    \l FormatType specified by \a type.
 +
 +    \sa monthName(), standaloneDayName()
 +*/
 +
 +/*!
 +    \qmlmethod string QtQuick2::Locale::standaloneDayName(day, type)
 +
 +    Returns the localized name of the \a day (where 0 represents
 +    Sunday, 1 represents Monday and so on) that is used as a
 +    standalone text, in the \l FormatType specified by \a type.
 +
 +    If the locale information does not specify the standalone day
 +    name then return value is the same as in dayName().
 +
 +    \sa dayName(), standaloneMonthName()
 +*/
 +
 +/*!
 +    \qmlproperty enumeration QtQuick2::Locale::firstDayOfWeek
 +
 +    Holds the first day of the week according to the current locale.
 +
 +    \list
 +    \o Locale.Sunday = 0
 +    \o Locale.Monday = 1
 +    \o Locale.Tuesday = 2
 +    \o Locale.Wednesday = 3
 +    \o Locale.Thursday = 4
 +    \o Locale.Friday = 5
 +    \o Locale.Saturday = 6
 +    \endlist
 +
 +    \note that these values match the JS Date API which is different
 +    from the Qt C++ API where Qt::Sunday = 7.
 +*/
 +
 +/*!
 +    \qmlproperty Array<int> QtQuick2::Locale::weekDays
 +
 +    Holds an array of days that are considered week days according to the current locale,
 +    where Sunday is 0 and Saturday is 6.
 +
 +    \sa firstDayOfWeek
 +*/
 +
 +/*!
 +    \qmlproperty Array<string> QtQuick2::Locale::uiLanguages
 +
 +    Returns an ordered list of locale names for translation purposes in
 +    preference order.
 +
 +    The return value represents locale names that the user expects to see the
 +    UI translation in.
 +
 +    The first item in the list is the most preferred one.
 +*/
 +
 +/*!
 +    \qmlproperty enumeration QtQuick2::Locale::textDirection
 +
 +    Holds the text direction of the language:
 +    \list
 +    \o Qt.LeftToRight
 +    \o Qt.RightToLeft
 +    \endlist
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::amText
 +
 +    The localized name of the "AM" suffix for times specified using the conventions of the 12-hour clock.
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::pmText
 +
 +    The localized name of the "PM" suffix for times specified using the conventions of the 12-hour clock.
 +*/
 +
 +/*!
 +    \qmlmethod string QtQuick2::Locale::currencySymbol(format)
 +
 +    Returns the currency symbol for the specified \a format:
 +    \list
 +    \o Locale.CurrencyIsoCode a ISO-4217 code of the currency.
 +    \o Locale.CurrencySymbol a currency symbol.
 +    \o Locale.CurrencyDisplayName a user readable name of the currency.
 +    \endlist
 +    \sa Number::toLocaleCurrencyString()
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::nativeLanguageName
 +
 +    Holds a native name of the language for the locale. For example
 +    "Schwiizertüütsch" for Swiss-German locale.
 +
 +    \sa nativeCountryName
 +*/
 +
 +/*!
 +    \qmlproperty string QtQuick2::Locale::nativeCountryName
 +
 +    Holds a native name of the country for the locale. For example
 +    "España" for Spanish/Spain locale.
 +
 +    \sa nativeLanguageName
 +*/
 +
 +/*!
 +    \qmlproperty enumeration QtQuick2::Locale::measurementSystem
 +
 +    This property defines which units are used for measurement.
 +
 +    \list
 +    \o Locale.MetricSystem This value indicates metric units, such as meters,
 +        centimeters and millimeters.
 +    \o Locale.ImperialSystem This value indicates imperial units, such as inches and
 +        miles. There are several distinct imperial systems in the world; this
 +        value stands for the official United States imperial units.
 +    \endlist
 +*/
 +
 +QT_END_NAMESPACE
index 9b132a4,0000000..93c6aa1
mode 100644,000000..100644
--- /dev/null
@@@ -1,889 -1,0 +1,891 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlpropertycache_p.h"
 +
 +#include "qqmlengine_p.h"
 +#include "qqmlbinding_p.h"
 +#include <private/qv8engine_p.h>
 +
 +#include <private/qmetaobject_p.h>
 +#include <private/qqmlaccessors_p.h>
 +
 +#include <QtCore/qdebug.h>
 +
++#include <ctype.h> // for toupper
++
 +Q_DECLARE_METATYPE(QJSValue)
 +Q_DECLARE_METATYPE(QQmlV8Handle);
 +
 +QT_BEGIN_NAMESPACE
 +
 +#define Q_INT16_MAX 32767
 +
 +class QQmlPropertyCacheMethodArguments 
 +{
 +public:
 +    QQmlPropertyCacheMethodArguments *next;
 +    int arguments[0];
 +};
 +
 +// Flags that do *NOT* depend on the property's QMetaProperty::userType() and thus are quick
 +// to load
 +static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p)
 +{
 +    QQmlPropertyData::Flags flags;
 +
 +    if (p.isConstant())
 +        flags |= QQmlPropertyData::IsConstant;
 +    if (p.isWritable())
 +        flags |= QQmlPropertyData::IsWritable;
 +    if (p.isResettable())
 +        flags |= QQmlPropertyData::IsResettable;
 +    if (p.isFinal())
 +        flags |= QQmlPropertyData::IsFinal;
 +    if (p.isEnumType())
 +        flags |= QQmlPropertyData::IsEnumType;
 +
 +    return flags;
 +}
 +
 +// Flags that do depend on the property's QMetaProperty::userType() and thus are slow to 
 +// load
 +static QQmlPropertyData::Flags flagsForPropertyType(int propType, QQmlEngine *engine)
 +{
 +    Q_ASSERT(propType != -1);
 +
 +    QQmlPropertyData::Flags flags;
 +
 +    if (propType == QMetaType::QObjectStar || propType == QMetaType::QWidgetStar) {
 +        flags |= QQmlPropertyData::IsQObjectDerived;
 +    } else if (propType == QMetaType::QVariant) {
 +        flags |= QQmlPropertyData::IsQVariant;
 +    } else if (propType < (int)QVariant::UserType) {
 +    } else if (propType == qMetaTypeId<QQmlBinding *>()) {
 +        flags |= QQmlPropertyData::IsQmlBinding;
 +    } else if (propType == qMetaTypeId<QJSValue>()) {
 +        flags |= QQmlPropertyData::IsQJSValue;
 +    } else if (propType == qMetaTypeId<QQmlV8Handle>()) {
 +        flags |= QQmlPropertyData::IsV8Handle;
 +    } else {
 +        QQmlMetaType::TypeCategory cat = 
 +            engine ? QQmlEnginePrivate::get(engine)->typeCategory(propType)
 +                   : QQmlMetaType::typeCategory(propType);
 +
 +        if (cat == QQmlMetaType::Object)
 +            flags |= QQmlPropertyData::IsQObjectDerived;
 +        else if (cat == QQmlMetaType::List)
 +            flags |= QQmlPropertyData::IsQList;
 +    }
 +
 +    return flags;
 +}
 +
 +static int metaObjectSignalCount(const QMetaObject *metaObject)
 +{
 +    int signalCount = 0;
 +    for (const QMetaObject *obj = metaObject; obj; obj = obj->superClass())
 +        signalCount += QMetaObjectPrivate::get(obj)->signalCount;
 +    return signalCount;
 +}
 +
 +QQmlPropertyData::Flags
 +QQmlPropertyData::flagsForProperty(const QMetaProperty &p, QQmlEngine *engine)
 +{
 +    return fastFlagsForProperty(p) | flagsForPropertyType(p.userType(), engine);
 +}
 +
 +void QQmlPropertyData::lazyLoad(const QMetaProperty &p, QQmlEngine *engine)
 +{
 +    Q_UNUSED(engine);
 +
 +    coreIndex = p.propertyIndex();
 +    notifyIndex = p.notifySignalIndex();
 +    Q_ASSERT(p.revision() <= Q_INT16_MAX);
 +    revision = p.revision();
 +
 +    flags = fastFlagsForProperty(p);
 +
 +    int type = p.type();
 +    if (type == QMetaType::QObjectStar || type == QMetaType::QWidgetStar) {
 +        propType = type;
 +        flags |= QQmlPropertyData::IsQObjectDerived;
 +    } else if (type == QMetaType::QVariant) {
 +        propType = type;
 +        flags |= QQmlPropertyData::IsQVariant;
 +    } else if (type == QVariant::UserType || type == -1) {
 +        propTypeName = p.typeName();
 +        flags |= QQmlPropertyData::NotFullyResolved;
 +    } else {
 +        propType = type;
 +    }
 +}
 +
 +void QQmlPropertyData::load(const QMetaProperty &p, QQmlEngine *engine)
 +{
 +    propType = p.userType();
 +    coreIndex = p.propertyIndex();
 +    notifyIndex = p.notifySignalIndex();
 +    flags = fastFlagsForProperty(p) | flagsForPropertyType(propType, engine);
 +    Q_ASSERT(p.revision() <= Q_INT16_MAX);
 +    revision = p.revision();
 +}
 +
 +void QQmlPropertyData::load(const QMetaMethod &m)
 +{
 +    coreIndex = m.methodIndex();
 +    arguments = 0;
 +    flags |= IsFunction;
 +    if (m.methodType() == QMetaMethod::Signal)
 +        flags |= IsSignal;
 +    propType = QVariant::Invalid;
 +
 +    const char *returnType = m.typeName();
 +    if (returnType) 
 +        propType = QMetaType::type(returnType);
 +
 +    const char *signature = m.signature();
 +    while (*signature != '(') { Q_ASSERT(*signature != 0); ++signature; }
 +
 +    ++signature;
 +    if (*signature != ')') {
 +        flags |= HasArguments;
 +        if (0 == ::strcmp(signature, "QQmlV8Function*)")) {
 +            flags |= IsV8Function;
 +        }
 +    }
 +
 +    Q_ASSERT(m.revision() <= Q_INT16_MAX);
 +    revision = m.revision();
 +}
 +
 +void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
 +{
 +    coreIndex = m.methodIndex();
 +    arguments = 0;
 +    flags |= IsFunction;
 +    if (m.methodType() == QMetaMethod::Signal)
 +        flags |= IsSignal;
 +    propType = QVariant::Invalid;
 +
 +    const char *returnType = m.typeName();
 +    if (returnType && *returnType) {
 +        propTypeName = returnType;
 +        flags |= NotFullyResolved;
 +    }
 +
 +    const char *signature = m.signature();
 +    while (*signature != '(') { Q_ASSERT(*signature != 0); ++signature; }
 +
 +    ++signature;
 +    if (*signature != ')') {
 +        flags |= HasArguments;
 +        if (0 == ::strcmp(signature, "QQmlV8Function*)")) {
 +            flags |= IsV8Function;
 +        }
 +    }
 +
 +    Q_ASSERT(m.revision() <= Q_INT16_MAX);
 +    revision = m.revision();
 +}
 +
 +/*!
 +Creates a new empty QQmlPropertyCache.
 +*/
 +QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e)
 +: engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
 +  signalHanderIndexCacheStart(0), metaObject(0), argumentsCache(0)
 +{
 +    Q_ASSERT(engine);
 +}
 +
 +/*!
 +Creates a new QQmlPropertyCache of \a metaObject.
 +*/
 +QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e, const QMetaObject *metaObject)
 +: engine(e), parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
 +  signalHanderIndexCacheStart(0), metaObject(0), argumentsCache(0)
 +{
 +    Q_ASSERT(engine);
 +    Q_ASSERT(metaObject);
 +
 +    update(engine, metaObject);
 +}
 +
 +QQmlPropertyCache::~QQmlPropertyCache()
 +{
 +    clear();
 +
 +    QQmlPropertyCacheMethodArguments *args = argumentsCache;
 +    while (args) {
 +        QQmlPropertyCacheMethodArguments *next = args->next;
 +        free(args);
 +        args = next;
 +    }
 +
 +    // We must clear this prior to releasing the parent incase it is a
 +    // linked hash
 +    stringCache.clear();
 +    if (parent) parent->release();
 +    parent = 0;
 +    engine = 0;
 +}
 +
 +void QQmlPropertyCache::destroy()
 +{
 +    Q_ASSERT(engine || constructor.IsEmpty());
 +    if (constructor.IsEmpty())
 +        delete this;
 +    else
 +        QQmlEnginePrivate::deleteInEngineThread(engine, this);
 +}
 +
 +// This is inherited from QQmlCleanup, so it should only clear the things
 +// that are tied to the specific QQmlEngine.
 +void QQmlPropertyCache::clear()
 +{
 +    qPersistentDispose(constructor);
 +    engine = 0;
 +}
 +
 +QQmlPropertyCache *QQmlPropertyCache::copy(int reserve)
 +{
 +    QQmlPropertyCache *cache = new QQmlPropertyCache(engine);
 +    cache->parent = this;
 +    cache->parent->addref();
 +    cache->propertyIndexCacheStart = propertyIndexCache.count() + propertyIndexCacheStart;
 +    cache->methodIndexCacheStart = methodIndexCache.count() + methodIndexCacheStart;
 +    cache->signalHanderIndexCacheStart = signalHandlerIndexCache.count() + signalHanderIndexCacheStart;
 +    cache->stringCache.linkAndReserve(stringCache, reserve);
 +    cache->allowedRevisionCache = allowedRevisionCache;
 +    cache->metaObject = metaObject;
 +
 +    // We specifically do *NOT* copy the constructor
 +
 +    return cache;
 +}
 +
 +QQmlPropertyCache *QQmlPropertyCache::copy()
 +{
 +    return copy(0);
 +}
 +
 +QQmlPropertyCache *
 +QQmlPropertyCache::copyAndAppend(QQmlEngine *engine, const QMetaObject *metaObject,
 +                                         QQmlPropertyData::Flag propertyFlags,
 +                                         QQmlPropertyData::Flag methodFlags,
 +                                         QQmlPropertyData::Flag signalFlags)
 +{
 +    return copyAndAppend(engine, metaObject, -1, propertyFlags, methodFlags, signalFlags);
 +}
 +
 +QQmlPropertyCache *
 +QQmlPropertyCache::copyAndAppend(QQmlEngine *engine, const QMetaObject *metaObject,
 +                                         int revision,
 +                                         QQmlPropertyData::Flag propertyFlags,
 +                                         QQmlPropertyData::Flag methodFlags,
 +                                         QQmlPropertyData::Flag signalFlags)
 +{
 +    Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4);
 +
 +    // Reserve enough space in the name hash for all the methods (including signals), all the
 +    // signal handlers and all the properties.  This assumes no name clashes, but this is the
 +    // common case.
 +    QQmlPropertyCache *rv = copy(QMetaObjectPrivate::get(metaObject)->methodCount +
 +                                         QMetaObjectPrivate::get(metaObject)->signalCount +
 +                                         QMetaObjectPrivate::get(metaObject)->propertyCount);
 +
 +    rv->append(engine, metaObject, revision, propertyFlags, methodFlags, signalFlags);
 +
 +    return rv;
 +}
 +
 +void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject, 
 +                                       QQmlPropertyData::Flag propertyFlags,
 +                                       QQmlPropertyData::Flag methodFlags,
 +                                       QQmlPropertyData::Flag signalFlags)
 +{
 +    append(engine, metaObject, -1, propertyFlags, methodFlags, signalFlags);
 +}
 +
 +void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject, 
 +                                       int revision, 
 +                                       QQmlPropertyData::Flag propertyFlags,
 +                                       QQmlPropertyData::Flag methodFlags,
 +                                       QQmlPropertyData::Flag signalFlags)
 +{
 +    Q_UNUSED(revision);
 +    Q_ASSERT(constructor.IsEmpty()); // We should not be appending to an in-use property cache
 +
 +    this->metaObject = metaObject;
 +
 +    bool dynamicMetaObject = isDynamicMetaObject(metaObject);
 +
 +    allowedRevisionCache.append(0);
 +
 +    int methodCount = metaObject->methodCount();
 +    Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4);
 +    int signalCount = metaObjectSignalCount(metaObject);
 +    int classInfoCount = QMetaObjectPrivate::get(metaObject)->classInfoCount;
 +
 +    QQmlAccessorProperties::Properties accessorProperties;
 +
 +    // Special case QObject as we don't want to add a qt_HasQmlAccessors classinfo to it
 +    if (metaObject == &QObject::staticMetaObject) {
 +        accessorProperties = QQmlAccessorProperties::properties(metaObject);
 +    } else if (classInfoCount) {
 +        int classInfoOffset = metaObject->classInfoOffset();
 +        bool hasFastProperty = false;
 +        for (int ii = 0; ii < classInfoCount; ++ii) {
 +            int idx = ii + classInfoOffset;
 +
 +            if (0 == qstrcmp(metaObject->classInfo(idx).name(), "qt_HasQmlAccessors")) {
 +                hasFastProperty = true;
 +                break;
 +            }
 +        }
 +
 +        if (hasFastProperty) {
 +            accessorProperties = QQmlAccessorProperties::properties(metaObject);
 +            if (accessorProperties.count == 0)
 +                qFatal("QQmlPropertyCache: %s has FastProperty class info, but has not "
 +                       "installed property accessors", metaObject->className());
 +        } else {
 +#ifndef QT_NO_DEBUG
 +            accessorProperties = QQmlAccessorProperties::properties(metaObject);
 +            if (accessorProperties.count != 0)
 +                qFatal("QQmlPropertyCache: %s has fast property accessors, but is missing "
 +                       "FastProperty class info", metaObject->className());
 +#endif
 +        }
 +    }
 +
 +    // qMax(defaultMethods, methodOffset) to block the signals and slots of QObject::staticMetaObject
 +    // incl. destroyed signals, objectNameChanged signal, deleteLater slot, _q_reregisterTimers slot.
 +    int methodOffset = qMax(QObject::staticMetaObject.methodCount(), metaObject->methodOffset());
 +    int signalOffset = signalCount - QMetaObjectPrivate::get(metaObject)->signalCount;
 +
 +    // update() should have reserved enough space in the vector that this doesn't cause a realloc
 +    // and invalidate the stringCache.
 +    methodIndexCache.resize(methodCount - methodIndexCacheStart);
 +    signalHandlerIndexCache.resize(signalCount - signalHanderIndexCacheStart);
 +    int signalHandlerIndex = signalOffset;
 +    for (int ii = methodOffset; ii < methodCount; ++ii) {
 +        QMetaMethod m = metaObject->method(ii);
 +        if (m.access() == QMetaMethod::Private) 
 +            continue;
 +
 +        // Extract method name
 +        const char *signature = m.signature();
 +        const char *cptr = signature;
 +        char utf8 = 0;
 +        while (*cptr != '(') {
 +            Q_ASSERT(*cptr != 0);
 +            utf8 |= *cptr & 0x80;
 +            ++cptr;
 +        }
 +
 +        QQmlPropertyData *data = &methodIndexCache[ii - methodIndexCacheStart];
 +        QQmlPropertyData *sigdata = 0;
 +
 +        data->lazyLoad(m);
 +
 +        if (data->isSignal())
 +            data->flags |= signalFlags;
 +        else
 +            data->flags |= methodFlags;
 +
 +        if (!dynamicMetaObject)
 +            data->flags |= QQmlPropertyData::IsDirect;
 +
 +        Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
 +        data->metaObjectOffset = allowedRevisionCache.count() - 1;
 +
 +        if (data->isSignal()) {
 +            sigdata = &signalHandlerIndexCache[signalHandlerIndex - signalHanderIndexCacheStart];
 +            *sigdata = *data;
 +            sigdata->flags |= QQmlPropertyData::IsSignalHandler;
 +        }
 +
 +        QQmlPropertyData *old = 0;
 +
 +        if (utf8) {
 +            QHashedString methodName(QString::fromUtf8(signature, cptr - signature));
 +            if (QQmlPropertyData **it = stringCache.value(methodName))
 +                old = *it;
 +            stringCache.insert(methodName, data);
 +
 +            if (data->isSignal()) {
 +                QHashedString on(QStringLiteral("on") % methodName.at(0).toUpper() % methodName.midRef(1));
 +                stringCache.insert(on, sigdata);
 +                ++signalHandlerIndex;
 +            }
 +        } else {
 +            QHashedCStringRef methodName(signature, cptr - signature);
 +            if (QQmlPropertyData **it = stringCache.value(methodName))
 +                old = *it;
 +            stringCache.insert(methodName, data);
 +
 +            if (data->isSignal()) {
 +                int length = methodName.length();
 +
 +                QVarLengthArray<char, 128> str(length+3);
 +                str[0] = 'o';
 +                str[1] = 'n';
 +                str[2] = toupper(signature[0]);
 +                if (length > 1)
 +                    memcpy(&str[3], &signature[1], length - 1);
 +                str[length + 2] = '\0';
 +
 +                QHashedString on(QString::fromLatin1(str.data()));
 +                stringCache.insert(on, sigdata);
 +                ++signalHandlerIndex;
 +            }
 +        }
 +
 +        if (old) {
 +            // We only overload methods in the same class, exactly like C++
 +            if (old->isFunction() && old->coreIndex >= methodOffset)
 +                data->flags |= QQmlPropertyData::IsOverload;
 +            data->overrideIndexIsProperty = !old->isFunction();
 +            data->overrideIndex = old->coreIndex;
 +        }
 +    }
 +
 +    int propCount = metaObject->propertyCount();
 +    int propOffset = metaObject->propertyOffset();
 +
 +    // update() should have reserved enough space in the vector that this doesn't cause a realloc
 +    // and invalidate the stringCache.
 +    propertyIndexCache.resize(propCount - propertyIndexCacheStart);
 +    for (int ii = propOffset; ii < propCount; ++ii) {
 +        QMetaProperty p = metaObject->property(ii);
 +        if (!p.isScriptable())
 +            continue;
 +
 +        const char *str = p.name();
 +        char utf8 = 0;
 +        const char *cptr = str;
 +        while (*cptr != 0) {
 +            utf8 |= *cptr & 0x80;
 +            ++cptr;
 +        }
 +
 +        QQmlPropertyData *data = &propertyIndexCache[ii - propertyIndexCacheStart];
 +
 +        data->lazyLoad(p, engine);
 +        data->flags |= propertyFlags;
 +
 +        if (!dynamicMetaObject) 
 +            data->flags |= QQmlPropertyData::IsDirect;
 +
 +        Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
 +        data->metaObjectOffset = allowedRevisionCache.count() - 1;
 +
 +        QQmlPropertyData *old = 0;
 +
 +        if (utf8) {
 +            QHashedString propName(QString::fromUtf8(str, cptr - str));
 +            if (QQmlPropertyData **it = stringCache.value(propName))
 +                old = *it;
 +            stringCache.insert(propName, data);
 +        } else {
 +            QHashedCStringRef propName(str, cptr - str);
 +            if (QQmlPropertyData **it = stringCache.value(propName))
 +                old = *it;
 +            stringCache.insert(propName, data);
 +        }
 +
 +        QQmlAccessorProperties::Property *accessorProperty = accessorProperties.property(str);
 +
 +        // Fast properties may not be overrides or revisioned
 +        Q_ASSERT(accessorProperty == 0 || (old == 0 && data->revision == 0));
 +
 +        if (accessorProperty) {
 +            data->flags |= QQmlPropertyData::HasAccessors;
 +            data->accessors = accessorProperty->accessors;
 +            data->accessorData = accessorProperty->data;
 +        } else if (old) {
 +            data->overrideIndexIsProperty = !old->isFunction();
 +            data->overrideIndex = old->coreIndex;
 +        }
 +    }
 +}
 +
 +void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
 +{
 +    Q_ASSERT(data->notFullyResolved());
 +
 +    data->propType = QMetaType::type(data->propTypeName);
 +
 +    if (!data->isFunction())
 +        data->flags |= flagsForPropertyType(data->propType, engine);
 +
 +    data->flags &= ~QQmlPropertyData::NotFullyResolved;
 +}
 +
 +void QQmlPropertyCache::updateRecur(QQmlEngine *engine, const QMetaObject *metaObject)
 +{
 +    if (!metaObject)
 +        return;
 +
 +    updateRecur(engine, metaObject->superClass());
 +
 +    append(engine, metaObject);
 +}
 +
 +void QQmlPropertyCache::update(QQmlEngine *engine, const QMetaObject *metaObject)
 +{
 +    Q_ASSERT(engine);
 +    Q_ASSERT(metaObject);
 +    Q_ASSERT(stringCache.isEmpty());
 +
 +    // Preallocate enough space in the index caches for all the properties/methods/signals that
 +    // are not cached in a parent cache so that the caches never need to be reallocated as this
 +    // would invalidate pointers stored in the stringCache.
 +    int pc = metaObject->propertyCount();
 +    int mc = metaObject->methodCount();
 +    int sc = metaObjectSignalCount(metaObject);
 +    propertyIndexCache.reserve(pc - propertyIndexCacheStart);
 +    methodIndexCache.reserve(mc - methodIndexCacheStart);
 +    signalHandlerIndexCache.reserve(sc - signalHanderIndexCacheStart);
 +
 +    // Reserve enough space in the stringCache for all properties/methods/signals including those
 +    // cached in a parent cache.
 +    stringCache.reserve(pc + mc + sc);
 +
 +    updateRecur(engine,metaObject);
 +}
 +
 +QQmlPropertyData *
 +QQmlPropertyCache::property(int index) const
 +{
 +    if (index < 0 || index >= (propertyIndexCacheStart + propertyIndexCache.count()))
 +        return 0;
 +    
 +    if (index < propertyIndexCacheStart)
 +        return parent->property(index);
 +
 +    QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&propertyIndexCache.at(index - propertyIndexCacheStart));
 +    if (rv->notFullyResolved()) resolve(rv);
 +    return rv;
 +}
 +
 +QQmlPropertyData *
 +QQmlPropertyCache::method(int index) const
 +{
 +    if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count()))
 +        return 0;
 +
 +    if (index < methodIndexCacheStart)
 +        return parent->method(index);
 +
 +    QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&methodIndexCache.at(index - methodIndexCacheStart));
 +    if (rv->notFullyResolved()) resolve(rv);
 +    return rv;
 +}
 +
 +QQmlPropertyData *
 +QQmlPropertyCache::property(const QHashedStringRef &str) const
 +{
 +    QQmlPropertyData **rv = stringCache.value(str);
 +    if (rv && (*rv)->notFullyResolved()) resolve(*rv);
 +    return rv?*rv:0;
 +}
 +
 +QQmlPropertyData *
 +QQmlPropertyCache::property(const QHashedCStringRef &str) const
 +{
 +    QQmlPropertyData **rv = stringCache.value(str);
 +    if (rv && (*rv)->notFullyResolved()) resolve(*rv);
 +    return rv?*rv:0;
 +}
 +
 +QQmlPropertyData *
 +QQmlPropertyCache::property(const QString &str) const
 +{
 +    QQmlPropertyData **rv = stringCache.value(str);
 +    if (rv && (*rv)->notFullyResolved()) resolve(*rv);
 +    return rv?*rv:0;
 +}
 +
 +QString QQmlPropertyData::name(QObject *object)
 +{
 +    if (!object)
 +        return QString();
 +
 +    return name(object->metaObject());
 +}
 +
 +QString QQmlPropertyData::name(const QMetaObject *metaObject)
 +{
 +    if (!metaObject || coreIndex == -1)
 +        return QString();
 +
 +    if (flags & IsFunction) {
 +        QMetaMethod m = metaObject->method(coreIndex);
 +
 +        QString name = QString::fromUtf8(m.signature());
 +        int parenIdx = name.indexOf(QLatin1Char('('));
 +        if (parenIdx != -1)
 +            name = name.left(parenIdx);
 +        return name;
 +    } else {
 +        QMetaProperty p = metaObject->property(coreIndex);
 +        return QString::fromUtf8(p.name());
 +    }
 +}
 +
 +QStringList QQmlPropertyCache::propertyNames() const
 +{
 +    QStringList keys;
 +    for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) 
 +        keys.append(iter.key());
 +    return keys;
 +}
 +
 +static int EnumType(const QMetaObject *meta, const QByteArray &str)
 +{
 +    QByteArray scope;
 +    QByteArray name;
 +    int scopeIdx = str.lastIndexOf("::");
 +    if (scopeIdx != -1) {
 +        scope = str.left(scopeIdx);
 +        name = str.mid(scopeIdx + 2);
 +    } else { 
 +        name = str;
 +    }
 +    for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
 +        QMetaEnum m = meta->enumerator(i);
 +        if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
 +            return QVariant::Int;
 +    }
 +    return QVariant::Invalid;
 +}
 +
 +// Returns an array of the arguments for method \a index.  The first entry in the array
 +// is the number of arguments.
 +int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index, 
 +                                                     QVarLengthArray<int, 9> &dummy,
 +                                                     QByteArray *unknownTypeError)
 +{
 +    Q_ASSERT(object && index >= 0);
 +
 +    QQmlData *ddata = QQmlData::get(object, false);
 +
 +    if (ddata && ddata->propertyCache) {
 +        typedef QQmlPropertyCacheMethodArguments A;
 +
 +        QQmlPropertyCache *c = ddata->propertyCache;
 +        Q_ASSERT(index < c->methodIndexCacheStart + c->methodIndexCache.count());
 +
 +        while (index < c->methodIndexCacheStart)
 +            c = c->parent;
 +
 +        QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&c->methodIndexCache.at(index - c->methodIndexCacheStart));
 +
 +        if (rv->arguments)  
 +            return static_cast<A *>(rv->arguments)->arguments;
 +
 +        const QMetaObject *metaObject = object->metaObject();
 +        QMetaMethod m = metaObject->method(index);
 +        QList<QByteArray> argTypeNames = m.parameterTypes();
 +
 +        A *args = static_cast<A *>(malloc(sizeof(A) + (argTypeNames.count() + 1) * sizeof(int)));
 +        args->arguments[0] = argTypeNames.count();
 +
 +        for (int ii = 0; ii < argTypeNames.count(); ++ii) {
 +            int type = QMetaType::type(argTypeNames.at(ii));
 +            if (type == QVariant::Invalid)
 +                type = EnumType(object->metaObject(), argTypeNames.at(ii));
 +            if (type == QVariant::Invalid) {
 +                if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
 +                free(args);
 +                return 0;
 +            }
 +            args->arguments[ii + 1] = type;
 +        }
 +
 +        rv->arguments = args;
 +        args->next = c->argumentsCache;
 +        c->argumentsCache = args;
 +        return static_cast<A *>(rv->arguments)->arguments;
 +
 +    } else {
 +        QMetaMethod m = object->metaObject()->method(index);
 +        QList<QByteArray> argTypeNames = m.parameterTypes();
 +        dummy.resize(argTypeNames.count() + 1);
 +        dummy[0] = argTypeNames.count();
 +
 +        for (int ii = 0; ii < argTypeNames.count(); ++ii) {
 +            int type = QMetaType::type(argTypeNames.at(ii));
 +            if (type == QVariant::Invalid)
 +                type = EnumType(object->metaObject(), argTypeNames.at(ii));
 +            if (type == QVariant::Invalid) {
 +                if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
 +                return 0;
 +            }
 +            dummy[ii + 1] = type;
 +        }
 +
 +        return dummy.data();
 +    }
 +}
 +
 +QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject,
 +                                                         const QString &property)
 +{
 +    Q_ASSERT(metaObject);
 +
 +    QQmlPropertyData rv;
 +    {
 +        const QMetaObject *cmo = metaObject;
 +        const QByteArray propertyName = property.toUtf8();
 +        while (cmo) {
 +            int idx = cmo->indexOfProperty(propertyName);
 +            if (idx != -1) {
 +                QMetaProperty p = cmo->property(idx);
 +                if (p.isScriptable()) {
 +                    rv.load(p);
 +                    return rv;
 +                } else {
 +                    while (cmo && cmo->propertyOffset() >= idx)
 +                        cmo = cmo->superClass();
 +                }
 +            } else {
 +                cmo = 0;
 +            }
 +        }
 +    }
 +
 +    int methodCount = metaObject->methodCount();
 +    int defaultMethods = QObject::staticMetaObject.methodCount();
 +    for (int ii = methodCount - 1; ii >= defaultMethods; --ii) {
 +        // >=defaultMethods to block the signals and slots of QObject::staticMetaObject
 +        // incl. destroyed signals, objectNameChanged signal, deleteLater slot, _q_reregisterTimers slot.
 +        QMetaMethod m = metaObject->method(ii);
 +        if (m.access() == QMetaMethod::Private)
 +            continue;
 +        QString methodName = QString::fromUtf8(m.signature());
 +
 +        int parenIdx = methodName.indexOf(QLatin1Char('('));
 +        Q_ASSERT(parenIdx != -1);
 +        QStringRef methodNameRef = methodName.leftRef(parenIdx);
 +
 +        if (methodNameRef == property) {
 +            rv.load(m);
 +            return rv;
 +        }
 +    }
 +
 +    return rv;
 +}
 +
 +inline const QString &qQmlPropertyCacheToString(const QString &string)
 +{
 +    return string;
 +}
 +
 +inline QString qQmlPropertyCacheToString(const QHashedV8String &string)
 +{
 +    return QV8Engine::toStringStatic(string.string());
 +}
 +
 +template<typename T>
 +QQmlPropertyData *
 +qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj,
 +                                  const T &name, QQmlPropertyData &local)
 +{
 +    QQmlPropertyCache *cache = 0;
 +
 +    if (engine) {
 +        QQmlData *ddata = QQmlData::get(obj);
 +
 +        if (ddata && ddata->propertyCache) {
 +            cache = ddata->propertyCache;
 +        } else if (engine) {
 +            QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
 +            cache = ep->cache(obj);
 +            if (cache) {
 +                ddata = QQmlData::get(obj, true);
 +                cache->addref();
 +                ddata->propertyCache = cache;
 +            }
 +        }
 +    }
 +
 +    QQmlPropertyData *rv = 0;
 +
 +    if (cache) {
 +        rv = cache->property(name);
 +    } else {
 +        local = qQmlPropertyCacheCreate(obj->metaObject(),
 +                                                qQmlPropertyCacheToString(name));
 +        if (local.isValid())
 +            rv = &local;
 +    }
 +
 +    return rv;
 +}
 +
 +QQmlPropertyData *
 +QQmlPropertyCache::property(QQmlEngine *engine, QObject *obj, 
 +                                    const QHashedV8String &name, QQmlPropertyData &local)
 +{
 +    return qQmlPropertyCacheProperty<QHashedV8String>(engine, obj, name, local);
 +}
 +
 +QQmlPropertyData *
 +QQmlPropertyCache::property(QQmlEngine *engine, QObject *obj,
 +                                    const QString &name, QQmlPropertyData &local)
 +{
 +    return qQmlPropertyCacheProperty<QString>(engine, obj, name, local);
 +}
 +
 +static inline const QMetaObjectPrivate *priv(const uint* data)
 +{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
 +
 +bool QQmlPropertyCache::isDynamicMetaObject(const QMetaObject *mo)
 +{
 +    return priv(mo->d.data)->revision >= 3 && priv(mo->d.data)->flags & DynamicMetaObject;
 +}
 +
 +QT_END_NAMESPACE
index 095ee79,0000000..a128cd9
mode 100644,000000..100644
--- /dev/null
@@@ -1,383 -1,0 +1,384 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLPROPERTYCACHE_P_H
 +#define QQMLPROPERTYCACHE_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/qqmlrefcount_p.h>
 +#include "qqmlcleanup_p.h"
 +#include "qqmlnotifier_p.h"
 +
 +#include <private/qhashedstring_p.h>
 +#include <QtCore/qvarlengtharray.h>
 +#include <QtCore/qvector.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QV8Engine;
 +class QMetaProperty;
 +class QV8QObjectWrapper;
 +class QQmlEngine;
 +class QQmlPropertyData;
 +class QQmlAccessors;
 +class QQmlPropertyCacheMethodArguments;
 +
 +// We have this somewhat awful split between RawData and Data so that RawData can be
 +// used in unions.  In normal code, you should always use Data which initializes RawData
 +// to an invalid state on construction.
 +class QQmlPropertyRawData
 +{
 +public:
 +    enum Flag {
 +        NoFlags           = 0x00000000,
 +        ValueTypeFlagMask = 0x0000FFFF, // Flags in valueTypeFlags must fit in this mask
 +
 +        // Can apply to all properties, except IsFunction
 +        IsConstant         = 0x00000001, // Has CONST flag
 +        IsWritable         = 0x00000002, // Has WRITE function
 +        IsResettable       = 0x00000004, // Has RESET function
 +        IsAlias            = 0x00000008, // Is a QML alias to another property
 +        IsFinal            = 0x00000010, // Has FINAL flag
 +        IsDirect           = 0x00000020, // Exists on a C++ QMetaObject
 +        HasAccessors       = 0x00000040, // Has property accessors
 +
 +        // These are mutualy exclusive
 +        IsFunction         = 0x00000080, // Is an invokable
 +        IsQObjectDerived   = 0x00000100, // Property type is a QObject* derived type
 +        IsEnumType         = 0x00000200, // Property type is an enum
 +        IsQList            = 0x00000400, // Property type is a QML list
 +        IsQmlBinding       = 0x00000800, // Property type is a QQmlBinding*
 +        IsQJSValue         = 0x00001000, // Property type is a QScriptValue
 +        IsV8Handle         = 0x00002000, // Property type is a QQmlV8Handle
 +        IsVMEProperty      = 0x00004000, // Property type is a "var" property of VMEMO
 +        IsValueTypeVirtual = 0x00008000, // Property is a value type "virtual" property
 +        IsQVariant         = 0x00010000, // Property is a QVariant
 +
 +        // Apply only to IsFunctions
 +        IsVMEFunction      = 0x00020000, // Function was added by QML
 +        HasArguments       = 0x00040000, // Function takes arguments
 +        IsSignal           = 0x00080000, // Function is a signal
 +        IsVMESignal        = 0x00100000, // Signal was added by QML
 +        IsV8Function       = 0x00200000, // Function takes QQmlV8Function* args
 +        IsSignalHandler    = 0x00400000, // Function is a signal handler
 +        IsOverload         = 0x00800000, // Function is an overload of another function
 +
 +        // Internal QQmlPropertyCache flags
 +        NotFullyResolved   = 0x01000000  // True if the type data is to be lazily resolved
 +    };
 +    Q_DECLARE_FLAGS(Flags, Flag)
 +
 +    Flags getFlags() const { return Flag(flags); }
 +    void setFlags(Flags f) { flags = f; }
 +
 +    bool isValid() const { return coreIndex != -1; }
 +
 +    bool isConstant() const { return flags & IsConstant; }
 +    bool isWritable() const { return flags & IsWritable; }
 +    bool isResettable() const { return flags & IsResettable; }
 +    bool isAlias() const { return flags & IsAlias; }
 +    bool isFinal() const { return flags & IsFinal; }
 +    bool isDirect() const { return flags & IsDirect; }
 +    bool hasAccessors() const { return flags & HasAccessors; }
 +    bool isFunction() const { return flags & IsFunction; }
 +    bool isQObject() const { return flags & IsQObjectDerived; }
 +    bool isEnum() const { return flags & IsEnumType; }
 +    bool isQList() const { return flags & IsQList; }
 +    bool isQmlBinding() const { return flags & IsQmlBinding; }
 +    bool isQJSValue() const { return flags & IsQJSValue; }
 +    bool isV8Handle() const { return flags & IsV8Handle; }
 +    bool isVMEProperty() const { return flags & IsVMEProperty; }
 +    bool isValueTypeVirtual() const { return flags & IsValueTypeVirtual; }
 +    bool isQVariant() const { return flags & IsQVariant; }
 +    bool isVMEFunction() const { return flags & IsVMEFunction; }
 +    bool hasArguments() const { return flags & HasArguments; }
 +    bool isSignal() const { return flags & IsSignal; }
 +    bool isVMESignal() const { return flags & IsVMESignal; }
 +    bool isV8Function() const { return flags & IsV8Function; }
 +    bool isSignalHandler() const { return flags & IsSignalHandler; }
 +    bool isOverload() const { return flags & IsOverload; }
 +
 +    bool hasOverride() const { return !(flags & IsValueTypeVirtual) &&
 +                                      !(flags & HasAccessors) &&
 +                                      overrideIndex >= 0; }
++    bool hasRevision() const { return !(flags & HasAccessors) && revision != 0; }
 +
 +    // Returns -1 if not a value type virtual property
 +    inline int getValueTypeCoreIndex() const;
 +
 +    // Returns the "encoded" index for use with bindings.  Encoding is:
 +    //     coreIndex | (valueTypeCoreIndex << 24)
 +    inline int encodedIndex() const;
 +
 +    union {
 +        int propType;             // When !NotFullyResolved
 +        const char *propTypeName; // When NotFullyResolved
 +    };
 +    int coreIndex;
 +    union {
 +        int notifyIndex;  // When !IsFunction
 +        void *arguments;  // When IsFunction && HasArguments
 +    };
 +
 +    union {
 +        struct { // When !HasAccessors
 +            qint16 revision;
 +            qint16 metaObjectOffset;
 +
 +            union {
 +                struct { // When IsValueTypeVirtual
 +                    quint16 valueTypeFlags; // flags of the access property on the value type proxy
 +                                            // object
 +                    quint8 valueTypePropType; // The QVariant::Type of access property on the value
 +                                              // type proxy object
 +                    quint8 valueTypeCoreIndex; // The prop index of the access property on the value
 +                                               // type proxy object
 +                };
 +
 +                struct { // When !IsValueTypeVirtual
 +                    uint overrideIndexIsProperty : 1;
 +                    signed int overrideIndex : 31;
 +                };
 +            };
 +        };
 +        struct { // When HasAccessors
 +            QQmlAccessors *accessors;
 +            intptr_t accessorData;
 +        };
 +    };
 +
 +private:
 +    friend class QQmlPropertyData;
 +    friend class QQmlPropertyCache;
 +    quint32 flags;
 +};
 +Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyRawData::Flags);
 +
 +class QQmlPropertyData : public QQmlPropertyRawData
 +{
 +public:
 +    inline QQmlPropertyData();
 +    inline QQmlPropertyData(const QQmlPropertyRawData &);
 +
 +    inline bool operator==(const QQmlPropertyRawData &);
 +
 +    static Flags flagsForProperty(const QMetaProperty &, QQmlEngine *engine = 0);
 +    void load(const QMetaProperty &, QQmlEngine *engine = 0);
 +    void load(const QMetaMethod &);
 +    QString name(QObject *);
 +    QString name(const QMetaObject *);
 +
 +private:
 +    friend class QQmlPropertyCache;
 +    void lazyLoad(const QMetaProperty &, QQmlEngine *engine = 0);
 +    void lazyLoad(const QMetaMethod &);
 +    bool notFullyResolved() const { return flags & NotFullyResolved; }
 +};
 +
 +class Q_QML_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
 +{
 +public:
 +    QQmlPropertyCache(QQmlEngine *);
 +    QQmlPropertyCache(QQmlEngine *, const QMetaObject *);
 +    virtual ~QQmlPropertyCache();
 +
 +    void update(QQmlEngine *, const QMetaObject *);
 +
 +    QQmlPropertyCache *copy();
 +
 +    QQmlPropertyCache *copyAndAppend(QQmlEngine *, const QMetaObject *,
 +                QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
 +                QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
 +                QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
 +    QQmlPropertyCache *copyAndAppend(QQmlEngine *, const QMetaObject *, int revision,
 +                QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
 +                QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
 +                QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
 +
 +    void append(QQmlEngine *, const QMetaObject *,
 +                QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
 +                QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
 +                QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
 +    void append(QQmlEngine *, const QMetaObject *, int revision,
 +                QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
 +                QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
 +                QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
 +
 +    inline QQmlPropertyData *property(const QHashedV8String &) const;
 +    QQmlPropertyData *property(const QHashedStringRef &) const;
 +    QQmlPropertyData *property(const QHashedCStringRef &) const;
 +    QQmlPropertyData *property(const QString &) const;
 +    QQmlPropertyData *property(int) const;
 +    QQmlPropertyData *method(int) const;
 +    QStringList propertyNames() const;
 +
 +    inline QQmlPropertyData *overrideData(QQmlPropertyData *) const;
 +    inline bool isAllowedInRevision(QQmlPropertyData *) const;
 +
 +    inline QQmlEngine *qmlEngine() const;
 +    static QQmlPropertyData *property(QQmlEngine *, QObject *, const QString &,
 +                                              QQmlPropertyData &);
 +    static QQmlPropertyData *property(QQmlEngine *, QObject *, const QHashedV8String &,
 +                                              QQmlPropertyData &);
 +    static int *methodParameterTypes(QObject *, int index, QVarLengthArray<int, 9> &dummy,
 +                                     QByteArray *unknownTypeError);
 +
 +    static bool isDynamicMetaObject(const QMetaObject *);
 +protected:
 +    virtual void destroy();
 +    virtual void clear();
 +
 +private:
 +    friend class QQmlEnginePrivate;
 +    friend class QV8QObjectWrapper;
 +
 +    inline QQmlPropertyCache *copy(int reserve);
 +
 +    // Implemented in v8/qv8qobjectwrapper.cpp
 +    v8::Local<v8::Object> newQObject(QObject *, QV8Engine *);
 +
 +    typedef QVector<QQmlPropertyData> IndexCache;
 +    typedef QStringHash<QQmlPropertyData *> StringCache;
 +    typedef QVector<int> AllowedRevisionCache;
 +
 +    void resolve(QQmlPropertyData *) const;
 +    void updateRecur(QQmlEngine *, const QMetaObject *);
 +
 +    QQmlEngine *engine;
 +    
 +    QQmlPropertyCache *parent;
 +    int propertyIndexCacheStart;
 +    int methodIndexCacheStart;
 +    int signalHanderIndexCacheStart;
 +
 +    IndexCache propertyIndexCache;
 +    IndexCache methodIndexCache;
 +    IndexCache signalHandlerIndexCache;
 +    StringCache stringCache;
 +    AllowedRevisionCache allowedRevisionCache;
 +    v8::Persistent<v8::Function> constructor;
 +
 +    const QMetaObject *metaObject;
 +    QQmlPropertyCacheMethodArguments *argumentsCache;
 +};
 +  
 +QQmlPropertyData::QQmlPropertyData()
 +{
 +    propType = 0;
 +    coreIndex = -1;
 +    notifyIndex = -1;
 +    overrideIndexIsProperty = false;
 +    overrideIndex = -1;
 +    revision = 0;
 +    metaObjectOffset = -1; 
 +    flags = 0;
 +}
 +
 +QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d)
 +{
 +    *(static_cast<QQmlPropertyRawData *>(this)) = d;
 +}
 +
 +bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
 +{
 +    return flags == other.flags &&
 +           propType == other.propType &&
 +           coreIndex == other.coreIndex &&
 +           notifyIndex == other.notifyIndex &&
 +           revision == other.revision &&
 +           (!isValueTypeVirtual() || 
 +            (valueTypeCoreIndex == other.valueTypeCoreIndex && 
 +             valueTypePropType == other.valueTypePropType));
 +}
 +
 +int QQmlPropertyRawData::getValueTypeCoreIndex() const
 +{
 +    return isValueTypeVirtual()?valueTypeCoreIndex:-1;
 +}
 +
 +int QQmlPropertyRawData::encodedIndex() const
 +{
 +    return isValueTypeVirtual()?(coreIndex | (valueTypeCoreIndex << 24)):coreIndex;
 +}
 +
 +QQmlPropertyData *
 +QQmlPropertyCache::overrideData(QQmlPropertyData *data) const
 +{
 +    if (!data->hasOverride())
 +        return 0;
 +
 +    if (data->overrideIndexIsProperty)
 +        return property(data->overrideIndex);
 +    else
 +        return method(data->overrideIndex);
 +}
 +
 +bool QQmlPropertyCache::isAllowedInRevision(QQmlPropertyData *data) const
 +{
 +    return (data->hasAccessors() || (data->metaObjectOffset == -1 && data->revision == 0)) ||
 +           (allowedRevisionCache[data->metaObjectOffset] >= data->revision);
 +}
 +
 +QQmlEngine *QQmlPropertyCache::qmlEngine() const
 +{
 +    return engine;
 +}
 +
 +QQmlPropertyData *QQmlPropertyCache::property(const QHashedV8String &str) const
 +{
 +    QQmlPropertyData **rv = stringCache.value(str);
 +    if (rv && (*rv)->notFullyResolved()) resolve(*rv);
 +    return rv?*rv:0;
 +}
 +
 +QT_END_NAMESPACE
 +
 +#endif // QQMLPROPERTYCACHE_P_H
index f8b8643,0000000..cf449c9
mode 100644,000000..100644
--- /dev/null
@@@ -1,74 -1,0 +1,77 @@@
- Q_DECLARE_INTERFACE(QQmlPropertyValueInterceptor, "com.trolltech.qml.QQmlPropertyValueInterceptor")
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLPROPERTYVALUEINTERCEPTOR_P_H
 +#define QQMLPROPERTYVALUEINTERCEPTOR_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 <QtQml/qtqmlglobal.h>
 +#include <QtCore/qobject.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QQmlProperty;
 +class Q_QML_EXPORT QQmlPropertyValueInterceptor
 +{
 +public:
 +    QQmlPropertyValueInterceptor();
 +    virtual ~QQmlPropertyValueInterceptor();
 +    virtual void setTarget(const QQmlProperty &property) = 0;
 +    virtual void write(const QVariant &value) = 0;
 +};
++
++#define QQmlPropertyValueInterceptor_iid "org.qt-project.Qt.QQmlPropertyValueInterceptor"
++
++Q_DECLARE_INTERFACE(QQmlPropertyValueInterceptor, QQmlPropertyValueInterceptor_iid)
 +
 +QT_END_NAMESPACE
 +
 +#endif // QQMLPROPERTYVALUEINTERCEPTOR_P_H
index 910b238,0000000..bbd3c2f
mode 100644,000000..100644
--- /dev/null
@@@ -1,67 -1,0 +1,70 @@@
- Q_DECLARE_INTERFACE(QQmlPropertyValueSource, "com.trolltech.qml.QQmlPropertyValueSource")
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLPROPERTYVALUESOURCE_H
 +#define QQMLPROPERTYVALUESOURCE_H
 +
 +#include <QtQml/qtqmlglobal.h>
 +#include <QtCore/qobject.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class QQmlProperty;
 +class Q_QML_EXPORT QQmlPropertyValueSource
 +{
 +public:
 +    QQmlPropertyValueSource();
 +    virtual ~QQmlPropertyValueSource();
 +    virtual void setTarget(const QQmlProperty &) = 0;
 +};
++
++#define QQmlPropertyValueSource_iid "org.qt-project.Qt.QQmlPropertyValueSource"
++
++Q_DECLARE_INTERFACE(QQmlPropertyValueSource, QQmlPropertyValueSource_iid)
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QQMLPROPERTYVALUESOURCE_H
index 828f7bf,0000000..72bd239
mode 100644,000000..100644
--- /dev/null
@@@ -1,441 -1,0 +1,424 @@@
-     /* When rewriting the code for bindings, we have to remove ILLEGAL JS tokens like newlines.
-        They're still in multi-line strings, because the QML parser allows them, but we have to
-        rewrite them to be JS compliant.
-        For performance reasons, we don't go for total correctness. \r is only replaced if a
-        \n was found (since most line endings are \n or \r\n) and QChar::LineSeparator is not
-        even considered. QTBUG-24064.
-        Note that rewriteSignalHandler has a function just like this one, for the same reason.
-     */
-     unsigned startOfString = ast->firstSourceLocation().begin() + 1 - _position;
-     unsigned stringLength = ast->firstSourceLocation().length - 2;
-     int lastIndex = -1;
-     bool foundNewLine = false;
-     QStringRef subStr(_code, startOfString, stringLength);
-     while (true) {
-         lastIndex = subStr.indexOf(QLatin1Char('\n'), lastIndex + 1);
-         if (lastIndex == -1)
-             break;
-         foundNewLine = true;
-         _writer->replace(startOfString+lastIndex, 1, QLatin1String("\\n"));
-     }
-     if (foundNewLine) {
-         while (true) {
-             lastIndex = subStr.indexOf(QLatin1Char('\r'), lastIndex + 1);
-             if (lastIndex == -1)
-                 break;
-             _writer->replace(startOfString+lastIndex, 1, QLatin1String("\\r"));
-         }
-     }
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlrewrite_p.h"
 +
 +#include <private/qqmlglobal_p.h>
 +
 +#include <QtCore/qdebug.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +DEFINE_BOOL_CONFIG_OPTION(rewriteDump, QML_REWRITE_DUMP);
 +
 +namespace QQmlRewrite {
 +
++static void rewriteStringLiteral(AST::StringLiteral *ast, const QString *code, int startPosition, TextWriter *writer)
++{
++    const unsigned position = ast->firstSourceLocation().begin() - startPosition + 1;
++    const unsigned length = ast->literalToken.length - 2;
++    const QStringRef spell = code->midRef(position, length);
++    const int end = spell.size();
++    int index = 0;
++
++    while (index < end) {
++        const QChar ch = spell.at(index++);
++
++        if (index < end && ch == QLatin1Char('\\')) {
++            int pos = index;
++
++            // skip a possibly empty sequence of \r characters
++            while (pos < end && spell.at(pos) == QLatin1Char('\r'))
++                ++pos;
++
++            if (pos < end && spell.at(pos) == QLatin1Char('\n')) {
++                // This is a `\' followed by a newline terminator.
++                // In this case there's nothing to replace. We keep the code
++                // as it is and we resume the searching.
++                index = pos + 1; // refresh the index
++            }
++        } else if (ch == QLatin1Char('\r') || ch == QLatin1Char('\n')) {
++            const QString sep = ch == QLatin1Char('\r') ? QLatin1String("\\r") : QLatin1String("\\n");
++            const int pos = index - 1;
++            QString s = sep;
++
++            while (index < end && spell.at(index) == ch) {
++                s += sep;
++                ++index;
++            }
++
++            writer->replace(position + pos, index - pos, s);
++        }
++    }
++}
++
 +bool SharedBindingTester::isSharable(const QString &code)
 +{
 +    Engine engine;
 +    Lexer lexer(&engine);
 +    Parser parser(&engine);
 +    lexer.setCode(code, 0);
 +    parser.parseStatement();
 +    if (!parser.statement()) 
 +        return false;
 +
 +    return isSharable(parser.statement());
 +}
 +
 +bool SharedBindingTester::isSharable(AST::Node *node)
 +{
 +    _sharable = true;
 +    AST::Node::acceptChild(node, this);
 +    return _sharable;
 +}
 +
 +QString RewriteBinding::operator()(const QString &code, bool *ok, bool *sharable)
 +{
 +    Engine engine;
 +    Lexer lexer(&engine);
 +    Parser parser(&engine);
 +    lexer.setCode(code, 0);
 +    parser.parseStatement();
 +    if (!parser.statement()) {
 +        if (ok) *ok = false;
 +        return QString();
 +    } else {
 +        if (ok) *ok = true;
 +        if (sharable) {
 +            SharedBindingTester tester;
 +            *sharable = tester.isSharable(parser.statement());
 +        }
 +    }
 +    return rewrite(code, 0, parser.statement());
 +}
 +
 +QString RewriteBinding::operator()(QQmlJS::AST::Node *node, const QString &code, bool *sharable)
 +{
 +    if (!node)
 +        return code;
 +
 +    if (sharable) {
 +        SharedBindingTester tester;
 +        *sharable = tester.isSharable(node);
 +    }
 +
 +    QQmlJS::AST::ExpressionNode *expression = node->expressionCast();
 +    QQmlJS::AST::Statement *statement = node->statementCast();
 +    if(!expression && !statement)
 +        return code;
 +
 +    TextWriter w;
 +    _writer = &w;
 +    _position = expression ? expression->firstSourceLocation().begin() : statement->firstSourceLocation().begin();
 +    _inLoop = 0;
 +    _code = &code;
 +
 +    accept(node);
 +
 +    unsigned startOfStatement = 0;
 +    unsigned endOfStatement = (expression ? expression->lastSourceLocation().end() : statement->lastSourceLocation().end()) - _position;
 +
 +    QString startString = QLatin1String("(function ") + _name + QLatin1String("() { ");
 +    if (expression)
 +        startString += QLatin1String("return ");
 +    _writer->replace(startOfStatement, 0, startString);
 +    _writer->replace(endOfStatement, 0, QLatin1String(" })"));
 +
 +    if (rewriteDump()) {
 +        qWarning() << "=============================================================";
 +        qWarning() << "Rewrote:";
 +        qWarning() << qPrintable(code);
 +    }
 +
 +    QString codeCopy = code;
 +    w.write(&codeCopy);
 +
 +    if (rewriteDump()) {
 +        qWarning() << "To:";
 +        qWarning() << qPrintable(codeCopy);
 +        qWarning() << "=============================================================";
 +    }
 +
 +    return codeCopy;
 +}
 +
 +void RewriteBinding::accept(AST::Node *node)
 +{
 +    AST::Node::acceptChild(node, this);
 +}
 +
 +QString RewriteBinding::rewrite(QString code, unsigned position,
 +                                AST::Statement *node)
 +{
 +    TextWriter w;
 +    _writer = &w;
 +    _position = position;
 +    _inLoop = 0;
 +    _code = &code;
 +
 +    accept(node);
 +
 +    unsigned startOfStatement = node->firstSourceLocation().begin() - _position;
 +    unsigned endOfStatement = node->lastSourceLocation().end() - _position;
 +
 +    _writer->replace(startOfStatement, 0, QLatin1String("(function ") + _name + QLatin1String("() { "));
 +    _writer->replace(endOfStatement, 0, QLatin1String(" })"));
 +
 +    if (rewriteDump()) {
 +        qWarning() << "=============================================================";
 +        qWarning() << "Rewrote:";
 +        qWarning() << qPrintable(code);
 +    }
 +
 +    w.write(&code);
 +
 +    if (rewriteDump()) {
 +        qWarning() << "To:";
 +        qWarning() << qPrintable(code);
 +        qWarning() << "=============================================================";
 +    }
 +
 +    return code;
 +}
 +
 +bool RewriteBinding::visit(AST::Block *ast)
 +{
 +    for (AST::StatementList *it = ast->statements; it; it = it->next) {
 +        if (! it->next) {
 +            // we need to rewrite only the last statement of a block.
 +            accept(it->statement);
 +        }
 +    }
 +
 +    return false;
 +}
 +
 +bool RewriteBinding::visit(AST::ExpressionStatement *ast)
 +{
 +    if (! _inLoop) {
 +        unsigned startOfExpressionStatement = ast->firstSourceLocation().begin() - _position;
 +        _writer->replace(startOfExpressionStatement, 0, QLatin1String("return "));
 +    }
 +
 +    return false;
 +}
 +
 +bool RewriteBinding::visit(AST::StringLiteral *ast)
 +{
-     unsigned startOfExpressionStatement = ast->firstSourceLocation().begin() - _position;
-     _strStarts << startOfExpressionStatement + 1;
-     _strLens << ast->firstSourceLocation().length - 2;
++    rewriteStringLiteral(ast, _code, _position, _writer);
 +    return false;
 +}
 +
 +bool RewriteBinding::visit(AST::DoWhileStatement *)
 +{
 +    ++_inLoop;
 +    return true;
 +}
 +
 +void RewriteBinding::endVisit(AST::DoWhileStatement *)
 +{
 +    --_inLoop;
 +}
 +
 +bool RewriteBinding::visit(AST::WhileStatement *)
 +{
 +    ++_inLoop;
 +    return true;
 +}
 +
 +void RewriteBinding::endVisit(AST::WhileStatement *)
 +{
 +    --_inLoop;
 +}
 +
 +bool RewriteBinding::visit(AST::ForStatement *)
 +{
 +    ++_inLoop;
 +    return true;
 +}
 +
 +void RewriteBinding::endVisit(AST::ForStatement *)
 +{
 +    --_inLoop;
 +}
 +
 +bool RewriteBinding::visit(AST::LocalForStatement *)
 +{
 +    ++_inLoop;
 +    return true;
 +}
 +
 +void RewriteBinding::endVisit(AST::LocalForStatement *)
 +{
 +    --_inLoop;
 +}
 +
 +bool RewriteBinding::visit(AST::ForEachStatement *)
 +{
 +    ++_inLoop;
 +    return true;
 +}
 +
 +void RewriteBinding::endVisit(AST::ForEachStatement *)
 +{
 +    --_inLoop;
 +}
 +
 +bool RewriteBinding::visit(AST::LocalForEachStatement *)
 +{
 +    ++_inLoop;
 +    return true;
 +}
 +
 +void RewriteBinding::endVisit(AST::LocalForEachStatement *)
 +{
 +    --_inLoop;
 +}
 +
 +bool RewriteBinding::visit(AST::CaseBlock *ast)
 +{
 +    // Process the initial sequence of the case clauses.
 +    for (AST::CaseClauses *it = ast->clauses; it; it = it->next) {
 +        // Return the value of the last statement in the block, if this is the last `case clause'
 +        // of the switch statement.
 +        bool returnTheValueOfLastStatement = (it->next == 0) && (ast->defaultClause == 0) && (ast->moreClauses == 0);
 +
 +        if (AST::CaseClause *clause = it->clause) {
 +            accept(clause->expression);
 +            rewriteCaseStatements(clause->statements, returnTheValueOfLastStatement);
 +        }
 +    }
 +
 +    // Process the default case clause
 +    if (ast->defaultClause) {
 +        // Return the value of the last statement in the block, if this is the last `case clause'
 +        // of the switch statement.
 +        bool rewriteTheLastStatement = (ast->moreClauses == 0);
 +
 +        rewriteCaseStatements(ast->defaultClause->statements, rewriteTheLastStatement);
 +    }
 +
 +    // Process trailing `case clauses'
 +    for (AST::CaseClauses *it = ast->moreClauses; it; it = it->next) {
 +        // Return the value of the last statement in the block, if this is the last `case clause'
 +        // of the switch statement.
 +        bool returnTheValueOfLastStatement = (it->next == 0);
 +
 +        if (AST::CaseClause *clause = it->clause) {
 +            accept(clause->expression);
 +            rewriteCaseStatements(clause->statements, returnTheValueOfLastStatement);
 +        }
 +    }
 +
 +    return false;
 +}
 +
 +void RewriteBinding::rewriteCaseStatements(AST::StatementList *statements, bool rewriteTheLastStatement)
 +{
 +    for (AST::StatementList *it = statements; it; it = it->next) {
 +        if (it->next && AST::cast<AST::BreakStatement *>(it->next->statement) != 0) {
 +            // The value of the first statement followed by a `break'.
 +            accept(it->statement);
 +            break;
 +        } else if (!it->next) {
 +            if (rewriteTheLastStatement)
 +                accept(it->statement);
 +            else if (AST::Block *block = AST::cast<AST::Block *>(it->statement))
 +                rewriteCaseStatements(block->statements, rewriteTheLastStatement);
 +        }
 +    }
 +}
 +
++RewriteSignalHandler::RewriteSignalHandler()
++    : _writer(0)
++    , _code(0)
++    , _position(0)
++{
++}
++
 +void RewriteSignalHandler::accept(AST::Node *node)
 +{
 +    AST::Node::acceptChild(node, this);
 +}
 +
 +bool RewriteSignalHandler::visit(AST::StringLiteral *ast)
 +{
- void RewriteSignalHandler::rewriteMultilineStrings(QString &code)
- {
-     QList<int> replaceR, replaceN;
-     for (int i=0; i < _strStarts.count(); i++) {
-         QStringRef curSubstr = QStringRef(&code, _strStarts[i], _strLens[i]);
-         int lastIndex = -1;
-         while (true) {
-             lastIndex = curSubstr.indexOf(QLatin1Char('\n'), lastIndex + 1);
-             if (lastIndex == -1)
-                 break;
-             replaceN << _strStarts[i]+lastIndex;
-         }
-         if (replaceN.count()) {
-             while (true) {
-                 lastIndex = curSubstr.indexOf(QLatin1Char('\r'), lastIndex + 1);
-                 if (lastIndex == -1)
-                     break;
-                 replaceR << _strStarts[i]+lastIndex;
-             }
-         }
-     }
-     for (int ii = replaceN.count() - 1; ii >= 0; ii--)
-         code.replace(replaceN[ii], 1, QLatin1String("\\n"));
-     if (replaceR.count())
-         for (int ii = replaceR.count() - 1; ii >= 0; ii--)
-             code.replace(replaceR[ii], 1, QLatin1String("\\r"));
- }
++    rewriteStringLiteral(ast, _code, _position, _writer);
 +    return false;
 +}
 +
-     _strStarts.clear();
-     _strLens.clear();
 +QString RewriteSignalHandler::operator()(QQmlJS::AST::Node *node, const QString &code, const QString &name)
 +{
 +    if (rewriteDump()) {
 +        qWarning() << "=============================================================";
 +        qWarning() << "Rewrote:";
 +        qWarning() << qPrintable(code);
 +    }
 +
 +    QQmlJS::AST::ExpressionNode *expression = node->expressionCast();
 +    QQmlJS::AST::Statement *statement = node->statementCast();
 +    if (!expression && !statement)
 +        return code;
 +
-     rewriteMultilineStrings(rewritten);
++    TextWriter w;
++    _writer = &w;
++    _code = &code;
++
 +    _position = expression ? expression->firstSourceLocation().begin() : statement->firstSourceLocation().begin();
 +    accept(node);
 +
 +    QString rewritten = code;
++    w.write(&rewritten);
 +
 +    rewritten = QStringLiteral("(function ") + name + QStringLiteral("() { ") + rewritten + QStringLiteral(" })");
 +
 +    if (rewriteDump()) {
 +        qWarning() << "To:";
 +        qWarning() << qPrintable(rewritten);
 +        qWarning() << "=============================================================";
 +    }
 +
 +    return rewritten;
 +}
 +
 +} // namespace QQmlRewrite
 +
 +QT_END_NAMESPACE
index e915d79,0000000..1d69839
mode 100644,000000..100644
--- /dev/null
@@@ -1,149 -1,0 +1,150 @@@
-     QList<int> _strStarts;
-     QList<int> _strLens;
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLREWRITE_P_H
 +#define QQMLREWRITE_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/textwriter_p.h>
 +#include <private/qqmljslexer_p.h>
 +#include <private/qqmljsparser_p.h>
 +#include <private/qqmljsmemorypool_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +namespace QQmlRewrite {
 +using namespace QQmlJS;
 +
 +class SharedBindingTester : protected AST::Visitor
 +{
 +    bool _sharable;
 +public:
 +    bool isSharable(const QString &code);
 +    bool isSharable(AST::Node *Node);
 +    
 +    virtual bool visit(AST::FunctionDeclaration *) { _sharable = false; return false; }
 +    virtual bool visit(AST::FunctionExpression *) { _sharable = false; return false; }
 +    virtual bool visit(AST::CallExpression *) { _sharable = false; return false; }
 +};
 +
 +class RewriteBinding: protected AST::Visitor
 +{
 +    unsigned _position;
 +    TextWriter *_writer;
 +    QString _name;
 +    const QString *_code;
 +
 +public:
 +    QString operator()(const QString &code, bool *ok = 0, bool *sharable = 0);
 +    QString operator()(QQmlJS::AST::Node *node, const QString &code, bool *sharable = 0);
 +
 +    //name of the function:  used for the debugger
 +    void setName(const QString &name) { _name = name; }
 +
 +protected:
 +    using AST::Visitor::visit;
 +
 +    void accept(AST::Node *node);
 +    QString rewrite(QString code, unsigned position, AST::Statement *node);
 +    void rewriteCaseStatements(AST::StatementList *statements, bool rewriteTheLastStatement);
 +
 +    virtual bool visit(AST::StringLiteral *ast);
 +    virtual bool visit(AST::Block *ast);
 +    virtual bool visit(AST::ExpressionStatement *ast);
 +
 +    virtual bool visit(AST::DoWhileStatement *ast);
 +    virtual void endVisit(AST::DoWhileStatement *ast);
 +
 +    virtual bool visit(AST::WhileStatement *ast);
 +    virtual void endVisit(AST::WhileStatement *ast);
 +
 +    virtual bool visit(AST::ForStatement *ast);
 +    virtual void endVisit(AST::ForStatement *ast);
 +
 +    virtual bool visit(AST::LocalForStatement *ast);
 +    virtual void endVisit(AST::LocalForStatement *ast);
 +
 +    virtual bool visit(AST::ForEachStatement *ast);
 +    virtual void endVisit(AST::ForEachStatement *ast);
 +
 +    virtual bool visit(AST::LocalForEachStatement *ast);
 +    virtual void endVisit(AST::LocalForEachStatement *ast);
 +
 +    virtual bool visit(AST::CaseBlock *ast);
 +
 +private:
 +    int _inLoop;
 +};
 +
 +class RewriteSignalHandler: protected AST::Visitor
 +{
++    TextWriter *_writer;
++    const QString *_code;
 +    int _position;
 +
 +public:
++    RewriteSignalHandler();
 +    QString operator()(QQmlJS::AST::Node *node, const QString &code, const QString &name);
 +
 +protected:
 +    void rewriteMultilineStrings(QString &code);
 +
 +    using AST::Visitor::visit;
 +    void accept(AST::Node *node);
 +    virtual bool visit(AST::StringLiteral *ast);
 +};
 +
 +} // namespace QQmlRewrite
 +
 +QT_END_NAMESPACE
 +
 +#endif // QQMLREWRITE_P_H
 +
index cde2885,0000000..5cbb2f6
mode 100644,000000..100644
--- /dev/null
@@@ -1,1928 -1,0 +1,1926 @@@
-     QQmlProfilerService::startRange(QQmlProfilerService::Compiling);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmltypeloader_p.h"
 +
 +#include <private/qqmlengine_p.h>
 +#include <private/qqmlglobal_p.h>
 +#include <private/qqmlthread_p.h>
 +#include <private/qqmlcompiler_p.h>
 +#include <private/qqmlcomponent_p.h>
 +#include <private/qqmlprofilerservice_p.h>
 +
 +#include <QtCore/qdir.h>
 +#include <QtCore/qfile.h>
 +#include <QtCore/qdebug.h>
 +#include <QtCore/qmutex.h>
 +#include <QtCore/qthread.h>
 +#include <QtCore/qdiriterator.h>
 +#include <QtCore/qwaitcondition.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtQml/qqmlextensioninterface.h>
 +
 +#if defined (Q_OS_UNIX)
 +#include <sys/types.h>
 +#include <dirent.h>
 +#endif
 +
 +// #define DATABLOB_DEBUG
 +
 +#ifdef DATABLOB_DEBUG
 +
 +#define ASSERT_MAINTHREAD() do { if(m_thread->isThisThread()) qFatal("QQmlDataLoader: Caller not in main thread"); } while(false)
 +#define ASSERT_LOADTHREAD() do { if(!m_thread->isThisThread()) qFatal("QQmlDataLoader: Caller not in load thread"); } while(false)
 +#define ASSERT_CALLBACK() do { if(!m_manager || !m_manager->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while(false)
 +
 +#else
 +
 +#define ASSERT_MAINTHREAD() 
 +#define ASSERT_LOADTHREAD()
 +#define ASSERT_CALLBACK()
 +
 +#endif
 +
 +QT_BEGIN_NAMESPACE
 +
 +// This is a lame object that we need to ensure that slots connected to
 +// QNetworkReply get called in the correct thread (the loader thread).  
 +// As QQmlDataLoader lives in the main thread, and we can't use
 +// Qt::DirectConnection connections from a QNetworkReply (because then 
 +// sender() wont work), we need to insert this object in the middle.
 +class QQmlDataLoaderNetworkReplyProxy : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l);
 +
 +public slots:
 +    void finished();
 +    void downloadProgress(qint64, qint64);
 +
 +private:
 +    QQmlDataLoader *l;
 +};
 +
 +class QQmlDataLoaderThread : public QQmlThread
 +{
 +    typedef QQmlDataLoaderThread This;
 +
 +public:
 +    QQmlDataLoaderThread(QQmlDataLoader *loader);
 +    QNetworkAccessManager *networkAccessManager() const;
 +    QQmlDataLoaderNetworkReplyProxy *networkReplyProxy() const;
 +
 +    void load(QQmlDataBlob *b);
 +    void loadAsync(QQmlDataBlob *b);
 +    void loadWithStaticData(QQmlDataBlob *b, const QByteArray &);
 +    void loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &);
 +    void callCompleted(QQmlDataBlob *b);
 +    void callDownloadProgressChanged(QQmlDataBlob *b, qreal p);
 +    void initializeEngine(QQmlExtensionInterface *, const char *);
 +
 +protected:
 +    virtual void shutdownThread();
 +
 +private:
 +    void loadThread(QQmlDataBlob *b);
 +    void loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &);
 +    void callCompletedMain(QQmlDataBlob *b);
 +    void callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p);
 +    void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri);
 +
 +    QQmlDataLoader *m_loader;
 +    mutable QNetworkAccessManager *m_networkAccessManager;
 +    mutable QQmlDataLoaderNetworkReplyProxy *m_networkReplyProxy;
 +};
 +
 +
 +QQmlDataLoaderNetworkReplyProxy::QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l) 
 +: l(l) 
 +{
 +}
 +
 +void QQmlDataLoaderNetworkReplyProxy::finished()
 +{
 +    Q_ASSERT(sender());
 +    Q_ASSERT(qobject_cast<QNetworkReply *>(sender()));
 +    QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
 +    l->networkReplyFinished(reply);
 +}
 +
 +void QQmlDataLoaderNetworkReplyProxy::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
 +{
 +    Q_ASSERT(sender());
 +    Q_ASSERT(qobject_cast<QNetworkReply *>(sender()));
 +    QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
 +    l->networkReplyProgress(reply, bytesReceived, bytesTotal);
 +}
 +
 +/*
 +Returns the set of QML files in path (qmldir, *.qml, *.js).  The caller
 +is responsible for deleting the returned data.
 +Returns 0 if the directory does not exist.
 +*/
 +#if defined (Q_OS_UNIX) && !defined(Q_OS_DARWIN)
 +static QStringHash<bool> *qmlFilesInDirectory(const QString &path)
 +{
 +    QByteArray name(QFile::encodeName(path));
 +    DIR *dd = opendir(name);
 +    if (!dd)
 +        return 0;
 +
 +    struct dirent *result;
 +    union {
 +        struct dirent d;
 +        char b[offsetof (struct dirent, d_name) + NAME_MAX + 1];
 +    } u;
 +
 +    QStringHash<bool> *files = new QStringHash<bool>;
 +    while (readdir_r(dd, &u.d, &result) == 0 && result != 0) {
 +        if (!strcmp(u.d.d_name, "qmldir")) {
 +            files->insert(QLatin1String("qmldir"), true);
 +            continue;
 +        }
 +        int len = strlen(u.d.d_name);
 +        if (len < 4)
 +            continue;
 +        if (!strcmp(u.d.d_name+len-4, ".qml") || !strcmp(u.d.d_name+len-3, ".js"))
 +            files->insert(QFile::decodeName(u.d.d_name), true);
 +#if defined(Q_OS_DARWIN)
 +        else if ((len > 6 && !strcmp(u.d.d_name+len-6, ".dylib")) || !strcmp(u.d.d_name+len-3, ".so")
 +                  || (len > 7 && !strcmp(u.d.d_name+len-7, ".bundle")))
 +            files->insert(QFile::decodeName(u.d.d_name), true);
 +#else  // Unix
 +        else if (!strcmp(u.d.d_name+len-3, ".so") || !strcmp(u.d.d_name+len-3, ".sl"))
 +            files->insert(QFile::decodeName(u.d.d_name), true);
 +#endif
 +    }
 +
 +    closedir(dd);
 +    return files;
 +}
 +#else
 +static QStringHash<bool> *qmlFilesInDirectory(const QString &path)
 +{
 +    QDirIterator dir(path, QDir::Files);
 +    if (!dir.hasNext())
 +        return 0;
 +    QStringHash<bool> *files = new QStringHash<bool>;
 +    while (dir.hasNext()) {
 +        dir.next();
 +        QString fileName = dir.fileName();
 +        if (fileName == QLatin1String("qmldir")
 +                || fileName.endsWith(QLatin1String(".qml"))
 +                || fileName.endsWith(QLatin1String(".js"))
 +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
 +                || fileName.endsWith(QLatin1String(".dll"))
 +#elif defined(Q_OS_DARWIN)
 +                || fileName.endsWith(QLatin1String(".dylib"))
 +                || fileName.endsWith(QLatin1String(".so"))
 +                || fileName.endsWith(QLatin1String(".bundle"))
 +#else  // Unix
 +                || fileName.endsWith(QLatin1String(".so"))
 +                || fileName.endsWith(QLatin1String(".sl"))
 +#endif
 +                ) {
 +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN)
 +            fileName = fileName.toLower();
 +#endif
 +            files->insert(fileName, true);
 +        }
 +    }
 +    return files;
 +}
 +#endif
 +
 +
 +/*!
 +\class QQmlDataBlob
 +\brief The QQmlDataBlob encapsulates a data request that can be issued to a QQmlDataLoader.
 +\internal
 +
 +QQmlDataBlob's are loaded by a QQmlDataLoader.  The user creates the QQmlDataBlob
 +and then calls QQmlDataLoader::load() or QQmlDataLoader::loadWithStaticData() to load it.
 +The QQmlDataLoader invokes callbacks on the QQmlDataBlob as data becomes available.
 +*/
 +
 +/*!
 +\enum QQmlDataBlob::Status
 +
 +This enum describes the status of the data blob.
 +
 +\list
 +\o Null The blob has not yet been loaded by a QQmlDataLoader
 +\o Loading The blob is loading network data.  The QQmlDataBlob::setData() callback has not yet been
 +invoked or has not yet returned.
 +\o WaitingForDependencies The blob is waiting for dependencies to be done before continueing.  This status
 +only occurs after the QQmlDataBlob::setData() callback has been made, and when the blob has outstanding
 +dependencies.
 +\o Complete The blob's data has been loaded and all dependencies are done.
 +\o Error An error has been set on this blob.
 +\endlist
 +*/
 +
 +/*!
 +\enum QQmlDataBlob::Type
 +
 +This enum describes the type of the data blob.
 +
 +\list
 +\o QmlFile This is a QQmlTypeData
 +\o JavaScriptFile This is a QQmlScriptData
 +\o QmldirFile This is a QQmlQmldirData
 +\endlist
 +*/
 +
 +/*!
 +Create a new QQmlDataBlob for \a url and of the provided \a type.
 +*/
 +QQmlDataBlob::QQmlDataBlob(const QUrl &url, Type type)
 +: m_type(type), m_url(url), m_finalUrl(url), m_manager(0), m_redirectCount(0), 
 +  m_inCallback(false), m_isDone(false)
 +{
 +}
 +
 +/*!  \internal */
 +QQmlDataBlob::~QQmlDataBlob()
 +{
 +    Q_ASSERT(m_waitingOnMe.isEmpty());
 +
 +    cancelAllWaitingFor();
 +}
 +
 +/*!
 +Returns the type provided to the constructor.
 +*/
 +QQmlDataBlob::Type QQmlDataBlob::type() const
 +{
 +    return m_type;
 +}
 +
 +/*!
 +Returns the blob's status.
 +*/
 +QQmlDataBlob::Status QQmlDataBlob::status() const
 +{
 +    return m_data.status();
 +}
 +
 +/*!
 +Returns true if the status is Null.
 +*/
 +bool QQmlDataBlob::isNull() const
 +{
 +    return status() == Null;
 +}
 +
 +/*!
 +Returns true if the status is Loading.
 +*/
 +bool QQmlDataBlob::isLoading() const
 +{
 +    return status() == Loading;
 +}
 +
 +/*!
 +Returns true if the status is WaitingForDependencies.
 +*/
 +bool QQmlDataBlob::isWaiting() const
 +{
 +    return status() == WaitingForDependencies;
 +}
 +
 +/*!
 +Returns true if the status is Complete.
 +*/
 +bool QQmlDataBlob::isComplete() const
 +{
 +    return status() == Complete;
 +}
 +
 +/*!
 +Returns true if the status is Error.
 +*/
 +bool QQmlDataBlob::isError() const
 +{
 +    return status() == Error;
 +}
 +
 +/*!
 +Returns true if the status is Complete or Error.
 +*/
 +bool QQmlDataBlob::isCompleteOrError() const
 +{
 +    Status s = status();
 +    return s == Error || s == Complete;
 +}
 +
 +/*!
 +Returns the data download progress from 0 to 1.
 +*/
 +qreal QQmlDataBlob::progress() const
 +{
 +    quint8 p = m_data.progress();
 +    if (p == 0xFF) return 1.;
 +    else return qreal(p) / qreal(0xFF);
 +}
 +
 +/*!
 +Returns the blob url passed to the constructor.  If a network redirect
 +happens while fetching the data, this url remains the same.
 +
 +\sa finalUrl()
 +*/
 +QUrl QQmlDataBlob::url() const
 +{
 +    return m_url;
 +}
 +
 +/*!
 +Returns the final url of the data.  Initially this is the same as
 +url(), but if a network redirect happens while fetching the data, this url
 +is updated to reflect the new location.
 +
 +May only be called from the load thread, or after the blob isCompleteOrError().
 +*/
 +QUrl QQmlDataBlob::finalUrl() const
 +{
 +    Q_ASSERT(isCompleteOrError() || (m_manager && m_manager->m_thread->isThisThread()));
 +    return m_finalUrl;
 +}
 +
 +/*!
 +Returns the finalUrl() as a string.
 +*/
 +QString QQmlDataBlob::finalUrlString() const
 +{
 +    Q_ASSERT(isCompleteOrError() || (m_manager && m_manager->m_thread->isThisThread()));
 +    if (m_finalUrlString.isEmpty())
 +        m_finalUrlString = m_finalUrl.toString();
 +
 +    return m_finalUrlString;
 +}
 +
 +/*!
 +Return the errors on this blob.
 +
 +May only be called from the load thread, or after the blob isCompleteOrError().
 +*/
 +QList<QQmlError> QQmlDataBlob::errors() const
 +{
 +    Q_ASSERT(isCompleteOrError() || (m_manager && m_manager->m_thread->isThisThread()));
 +    return m_errors;
 +}
 +
 +/*!
 +Mark this blob as having \a errors.
 +
 +All outstanding dependencies will be cancelled.  Requests to add new dependencies 
 +will be ignored.  Entry into the Error state is irreversable.
 +
 +The setError() method may only be called from within a QQmlDataBlob callback.
 +*/
 +void QQmlDataBlob::setError(const QQmlError &errors)
 +{
 +    ASSERT_CALLBACK();
 +
 +    QList<QQmlError> l;
 +    l << errors;
 +    setError(l);
 +}
 +
 +/*!
 +\overload
 +*/
 +void QQmlDataBlob::setError(const QList<QQmlError> &errors)
 +{
 +    ASSERT_CALLBACK();
 +
 +    Q_ASSERT(status() != Error);
 +    Q_ASSERT(m_errors.isEmpty());
 +
 +    m_errors = errors; // Must be set before the m_data fence
 +    m_data.setStatus(Error);
 +
 +    cancelAllWaitingFor();
 +
 +    if (!m_inCallback)
 +        tryDone();
 +}
 +
 +/*! 
 +Wait for \a blob to become complete or to error.  If \a blob is already 
 +complete or in error, or this blob is already complete, this has no effect.
 +
 +The setError() method may only be called from within a QQmlDataBlob callback.
 +*/
 +void QQmlDataBlob::addDependency(QQmlDataBlob *blob)
 +{
 +    ASSERT_CALLBACK();
 +
 +    Q_ASSERT(status() != Null);
 +
 +    if (!blob ||
 +        blob->status() == Error || blob->status() == Complete ||
 +        status() == Error || status() == Complete || m_isDone || 
 +        m_waitingFor.contains(blob))
 +        return;
 +
 +    blob->addref();
 +
 +    m_data.setStatus(WaitingForDependencies);
 +
 +    m_waitingFor.append(blob);
 +    blob->m_waitingOnMe.append(this);
 +}
 +
 +/*!
 +\fn void QQmlDataBlob::dataReceived(const QByteArray &data)
 +
 +Invoked when data for the blob is received.  Implementors should use this callback
 +to determine a blob's dependencies.  Within this callback you may call setError()
 +or addDependency().
 +*/
 +
 +/*!
 +Invoked once data has either been received or a network error occurred, and all 
 +dependencies are complete.
 +
 +You can set an error in this method, but you cannot add new dependencies.  Implementors
 +should use this callback to finalize processing of data.
 +
 +The default implementation does nothing.
 +
 +XXX Rename processData() or some such to avoid confusion between done() (processing thread)
 +and completed() (main thread)
 +*/
 +void QQmlDataBlob::done()
 +{
 +}
 +
 +/*!
 +Invoked if there is a network error while fetching this blob.
 +
 +The default implementation sets an appropriate QQmlError.
 +*/
 +void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError)
 +{
 +    Q_UNUSED(networkError);
 +
 +    QQmlError error;
 +    error.setUrl(m_finalUrl);
 +
 +    const char *errorString = 0;
 +    switch (networkError) {
 +        default:
 +            errorString = "Network error";
 +            break;
 +        case QNetworkReply::ConnectionRefusedError:
 +            errorString = "Connection refused";
 +            break;
 +        case QNetworkReply::RemoteHostClosedError:
 +            errorString = "Remote host closed the connection";
 +            break;
 +        case QNetworkReply::HostNotFoundError:
 +            errorString = "Host not found";
 +            break;
 +        case QNetworkReply::TimeoutError:
 +            errorString = "Timeout";
 +            break;
 +        case QNetworkReply::ProxyConnectionRefusedError:
 +        case QNetworkReply::ProxyConnectionClosedError:
 +        case QNetworkReply::ProxyNotFoundError:
 +        case QNetworkReply::ProxyTimeoutError:
 +        case QNetworkReply::ProxyAuthenticationRequiredError:
 +        case QNetworkReply::UnknownProxyError:
 +            errorString = "Proxy error";
 +            break;
 +        case QNetworkReply::ContentAccessDenied:
 +            errorString = "Access denied";
 +            break;
 +        case QNetworkReply::ContentNotFoundError:
 +            errorString = "File not found";
 +            break;
 +        case QNetworkReply::AuthenticationRequiredError:
 +            errorString = "Authentication required";
 +            break;
 +    };
 +
 +    error.setDescription(QLatin1String(errorString));
 +
 +    setError(error);
 +}
 +
 +/*! 
 +Called if \a blob, which was previously waited for, has an error.
 +
 +The default implementation does nothing.
 +*/
 +void QQmlDataBlob::dependencyError(QQmlDataBlob *blob)
 +{
 +    Q_UNUSED(blob);
 +}
 +
 +/*!
 +Called if \a blob, which was previously waited for, has completed.
 +
 +The default implementation does nothing.
 +*/
 +void QQmlDataBlob::dependencyComplete(QQmlDataBlob *blob)
 +{
 +    Q_UNUSED(blob);
 +}
 +
 +/*! 
 +Called when all blobs waited for have completed.  This occurs regardless of 
 +whether they are in error, or complete state.  
 +
 +The default implementation does nothing.
 +*/
 +void QQmlDataBlob::allDependenciesDone()
 +{
 +}
 +
 +/*!
 +Called when the download progress of this blob changes.  \a progress goes
 +from 0 to 1.
 +
 +This callback is only invoked if an asynchronous load for this blob is 
 +made.  An asynchronous load is one in which the Asynchronous mode is
 +specified explicitly, or one that is implicitly delayed due to a network 
 +operation.
 +
 +The default implementation does nothing.
 +*/
 +void QQmlDataBlob::downloadProgressChanged(qreal progress)
 +{
 +    Q_UNUSED(progress);
 +}
 +
 +/*!
 +Invoked on the main thread sometime after done() was called on the load thread.
 +
 +You cannot modify the blobs state at all in this callback and cannot depend on the
 +order or timeliness of these callbacks.  Implementors should use this callback to notify 
 +dependencies on the main thread that the blob is done and not a lot else.
 +
 +This callback is only invoked if an asynchronous load for this blob is 
 +made.  An asynchronous load is one in which the Asynchronous mode is
 +specified explicitly, or one that is implicitly delayed due to a network 
 +operation.
 +
 +The default implementation does nothing.
 +*/
 +void QQmlDataBlob::completed()
 +{
 +}
 +
 +
 +void QQmlDataBlob::tryDone()
 +{
 +    if (status() != Loading && m_waitingFor.isEmpty() && !m_isDone) {
 +        m_isDone = true;
 +        addref();
 +
 +#ifdef DATABLOB_DEBUG
 +        qWarning("QQmlDataBlob::done() %s", qPrintable(url().toString()));
 +#endif
 +        done();
 +
 +        if (status() != Error)
 +            m_data.setStatus(Complete);
 +
 +        notifyAllWaitingOnMe();
 +
 +        // Locking is not required here, as anyone expecting callbacks must
 +        // already be protected against the blob being completed (as set above);
 +        if (m_data.isAsync()) {
 +#ifdef DATABLOB_DEBUG
 +            qWarning("QQmlDataBlob: Dispatching completed");
 +#endif
 +            m_manager->m_thread->callCompleted(this);
 +        }
 +
 +        release();
 +    }
 +}
 +
 +void QQmlDataBlob::cancelAllWaitingFor()
 +{
 +    while (m_waitingFor.count()) {
 +        QQmlDataBlob *blob = m_waitingFor.takeLast();
 +
 +        Q_ASSERT(blob->m_waitingOnMe.contains(this));
 +
 +        blob->m_waitingOnMe.removeOne(this);
 +
 +        blob->release();
 +    }
 +}
 +
 +void QQmlDataBlob::notifyAllWaitingOnMe()
 +{
 +    while (m_waitingOnMe.count()) {
 +        QQmlDataBlob *blob = m_waitingOnMe.takeLast();
 +
 +        Q_ASSERT(blob->m_waitingFor.contains(this));
 +
 +        blob->notifyComplete(this);
 +    }
 +}
 +
 +void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
 +{
 +    Q_ASSERT(m_waitingFor.contains(blob));
 +    Q_ASSERT(blob->status() == Error || blob->status() == Complete);
 +
 +    m_inCallback = true;
 +
 +    if (blob->status() == Error) {
 +        dependencyError(blob);
 +    } else if (blob->status() == Complete) {
 +        dependencyComplete(blob);
 +    }
 +
 +    m_waitingFor.removeOne(blob);
 +    blob->release();
 +
 +    if (!isError() && m_waitingFor.isEmpty()) 
 +        allDependenciesDone();
 +
 +    m_inCallback = false;
 +
 +    tryDone();
 +}
 +
 +#define TD_STATUS_MASK 0x0000FFFF
 +#define TD_STATUS_SHIFT 0
 +#define TD_PROGRESS_MASK 0x00FF0000
 +#define TD_PROGRESS_SHIFT 16
 +#define TD_ASYNC_MASK 0x80000000
 +
 +QQmlDataBlob::ThreadData::ThreadData()
 +: _p(0)
 +{
 +}
 +
 +QQmlDataBlob::Status QQmlDataBlob::ThreadData::status() const
 +{
 +    return QQmlDataBlob::Status((_p.load() & TD_STATUS_MASK) >> TD_STATUS_SHIFT);
 +}
 +
 +void QQmlDataBlob::ThreadData::setStatus(QQmlDataBlob::Status status)
 +{
 +    while (true) {
 +        int d = _p.load();
 +        int nd = (d & ~TD_STATUS_MASK) | ((status << TD_STATUS_SHIFT) & TD_STATUS_MASK);
 +        if (d == nd || _p.testAndSetOrdered(d, nd)) return;
 +    }
 +}
 +
 +bool QQmlDataBlob::ThreadData::isAsync() const
 +{
 +    return _p.load() & TD_ASYNC_MASK;
 +}
 +
 +void QQmlDataBlob::ThreadData::setIsAsync(bool v)
 +{
 +    while (true) {
 +        int d = _p.load();
 +        int nd = (d & ~TD_ASYNC_MASK) | (v?TD_ASYNC_MASK:0);
 +        if (d == nd || _p.testAndSetOrdered(d, nd)) return;
 +    }
 +}
 +
 +quint8 QQmlDataBlob::ThreadData::progress() const
 +{
 +    return quint8((_p.load() & TD_PROGRESS_MASK) >> TD_PROGRESS_SHIFT);
 +}
 +
 +void QQmlDataBlob::ThreadData::setProgress(quint8 v)
 +{
 +    while (true) {
 +        int d = _p.load();
 +        int nd = (d & ~TD_PROGRESS_MASK) | ((v << TD_PROGRESS_SHIFT) & TD_PROGRESS_MASK);
 +        if (d == nd || _p.testAndSetOrdered(d, nd)) return;
 +    }
 +}
 +
 +QQmlDataLoaderThread::QQmlDataLoaderThread(QQmlDataLoader *loader)
 +: m_loader(loader), m_networkAccessManager(0), m_networkReplyProxy(0)
 +{
 +}
 +
 +QNetworkAccessManager *QQmlDataLoaderThread::networkAccessManager() const
 +{
 +    Q_ASSERT(isThisThread());
 +    if (!m_networkAccessManager) {
 +        m_networkAccessManager = QQmlEnginePrivate::get(m_loader->engine())->createNetworkAccessManager(0);
 +        m_networkReplyProxy = new QQmlDataLoaderNetworkReplyProxy(m_loader);
 +    }
 +
 +    return m_networkAccessManager;
 +}
 +
 +QQmlDataLoaderNetworkReplyProxy *QQmlDataLoaderThread::networkReplyProxy() const
 +{
 +    Q_ASSERT(isThisThread());
 +    Q_ASSERT(m_networkReplyProxy); // Must call networkAccessManager() first
 +    return m_networkReplyProxy;
 +}
 +
 +void QQmlDataLoaderThread::load(QQmlDataBlob *b) 
 +{ 
 +    b->addref();
 +    callMethodInThread(&This::loadThread, b); 
 +}
 +
 +void QQmlDataLoaderThread::loadAsync(QQmlDataBlob *b)
 +{
 +    b->addref();
 +    postMethodToThread(&This::loadThread, b);
 +}
 +
 +void QQmlDataLoaderThread::loadWithStaticData(QQmlDataBlob *b, const QByteArray &d)
 +{
 +    b->addref();
 +    callMethodInThread(&This::loadWithStaticDataThread, b, d);
 +}
 +
 +void QQmlDataLoaderThread::loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &d)
 +{
 +    b->addref();
 +    postMethodToThread(&This::loadWithStaticDataThread, b, d);
 +}
 +
 +void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b) 
 +{ 
 +    b->addref(); 
 +    postMethodToMain(&This::callCompletedMain, b); 
 +}
 +
 +void QQmlDataLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p) 
 +{ 
 +    b->addref(); 
 +    postMethodToMain(&This::callDownloadProgressChangedMain, b, p); 
 +}
 +
 +void QQmlDataLoaderThread::initializeEngine(QQmlExtensionInterface *iface, 
 +                                                    const char *uri)
 +{
 +    callMethodInMain(&This::initializeEngineMain, iface, uri);
 +}
 +
 +void QQmlDataLoaderThread::shutdownThread()
 +{
 +    delete m_networkAccessManager;
 +    m_networkAccessManager = 0;
 +    delete m_networkReplyProxy;
 +    m_networkReplyProxy = 0;
 +}
 +
 +void QQmlDataLoaderThread::loadThread(QQmlDataBlob *b) 
 +{ 
 +    m_loader->loadThread(b); 
 +    b->release();
 +}
 +
 +void QQmlDataLoaderThread::loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &d)
 +{
 +    m_loader->loadWithStaticDataThread(b, d);
 +    b->release();
 +}
 +
 +void QQmlDataLoaderThread::callCompletedMain(QQmlDataBlob *b) 
 +{ 
 +#ifdef DATABLOB_DEBUG
 +    qWarning("QQmlDataLoaderThread: %s completed() callback", qPrintable(b->url().toString())); 
 +#endif
 +    b->completed(); 
 +    b->release(); 
 +}
 +
 +void QQmlDataLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p) 
 +{ 
 +#ifdef DATABLOB_DEBUG
 +    qWarning("QQmlDataLoaderThread: %s downloadProgressChanged(%f) callback", 
 +             qPrintable(b->url().toString()), p); 
 +#endif
 +    b->downloadProgressChanged(p); 
 +    b->release(); 
 +}
 +
 +void QQmlDataLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface, 
 +                                                        const char *uri)
 +{
 +    Q_ASSERT(m_loader->engine()->thread() == QThread::currentThread());
 +    iface->initializeEngine(m_loader->engine(), uri);
 +}
 +
 +/*!
 +\class QQmlDataLoader
 +\brief The QQmlDataLoader class abstracts loading files and their dependencies over the network.
 +\internal
 +
 +The QQmlDataLoader class is provided for the exclusive use of the QQmlTypeLoader class.
 +
 +Clients create QQmlDataBlob instances and submit them to the QQmlDataLoader class
 +through the QQmlDataLoader::load() or QQmlDataLoader::loadWithStaticData() methods.
 +The loader then fetches the data over the network or from the local file system in an efficient way.
 +QQmlDataBlob is an abstract class, so should always be specialized.
 +
 +Once data is received, the QQmlDataBlob::dataReceived() method is invoked on the blob.  The
 +derived class should use this callback to process the received data.  Processing of the data can 
 +result in an error being set (QQmlDataBlob::setError()), or one or more dependencies being
 +created (QQmlDataBlob::addDependency()).  Dependencies are other QQmlDataBlob's that
 +are required before processing can fully complete.
 +
 +To complete processing, the QQmlDataBlob::done() callback is invoked.  done() is called when
 +one of these three preconditions are met.
 +
 +\list 1
 +\o The QQmlDataBlob has no dependencies.
 +\o The QQmlDataBlob has an error set.
 +\o All the QQmlDataBlob's dependencies are themselves "done()".
 +\endlist
 +
 +Thus QQmlDataBlob::done() will always eventually be called, even if the blob has an error set.
 +*/
 +
 +/*!
 +Create a new QQmlDataLoader for \a engine.
 +*/
 +QQmlDataLoader::QQmlDataLoader(QQmlEngine *engine)
 +: m_engine(engine), m_thread(new QQmlDataLoaderThread(this))
 +{
 +}
 +
 +/*! \internal */
 +QQmlDataLoader::~QQmlDataLoader()
 +{
 +    for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter) 
 +        (*iter)->release();
 +
 +    m_thread->shutdown();
 +    delete m_thread;
 +}
 +
 +void QQmlDataLoader::lock()
 +{
 +    m_thread->lock();
 +}
 +
 +void QQmlDataLoader::unlock()
 +{
 +    m_thread->unlock();
 +}
 +
 +/*!
 +Load the provided \a blob from the network or filesystem.
 +
 +The loader must be locked.
 +*/
 +void QQmlDataLoader::load(QQmlDataBlob *blob, Mode mode)
 +{
 +#ifdef DATABLOB_DEBUG
 +    qWarning("QQmlDataLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()), 
 +             m_thread->isThisThread()?"Compile":"Engine");
 +#endif
 +
 +    Q_ASSERT(blob->status() == QQmlDataBlob::Null);
 +    Q_ASSERT(blob->m_manager == 0);
 +
 +    blob->m_data.setStatus(QQmlDataBlob::Loading);
 +    blob->m_manager = this;
 +
 +    if (m_thread->isThisThread()) {
 +        unlock();
 +        loadThread(blob);
 +        lock();
 +    } else if (mode == PreferSynchronous) {
 +        unlock();
 +        m_thread->load(blob);
 +        lock();
 +        if (!blob->isCompleteOrError())
 +            blob->m_data.setIsAsync(true);
 +    } else {
 +        Q_ASSERT(mode == Asynchronous);
 +        blob->m_data.setIsAsync(true);
 +        unlock();
 +        m_thread->loadAsync(blob);
 +        lock();
 +    }
 +}
 +
 +/*!
 +Load the provided \a blob with \a data.  The blob's URL is not used by the data loader in this case.
 +
 +The loader must be locked.
 +*/
 +void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode)
 +{
 +#ifdef DATABLOB_DEBUG
 +    qWarning("QQmlDataLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()), 
 +             m_thread->isThisThread()?"Compile":"Engine");
 +#endif
 +
 +    Q_ASSERT(blob->status() == QQmlDataBlob::Null);
 +    Q_ASSERT(blob->m_manager == 0);
 +    
 +    blob->m_data.setStatus(QQmlDataBlob::Loading);
 +    blob->m_manager = this;
 +
 +    if (m_thread->isThisThread()) {
 +        unlock();
 +        loadWithStaticDataThread(blob, data);
 +        lock();
 +    } else if (mode == PreferSynchronous) {
 +        unlock();
 +        m_thread->loadWithStaticData(blob, data);
 +        lock();
 +        if (!blob->isCompleteOrError())
 +            blob->m_data.setIsAsync(true);
 +    } else {
 +        Q_ASSERT(mode == Asynchronous);
 +        blob->m_data.setIsAsync(true);
 +        unlock();
 +        m_thread->loadWithStaticDataAsync(blob, data);
 +        lock();
 +    }
 +}
 +
 +void QQmlDataLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data)
 +{
 +    ASSERT_LOADTHREAD();
 +
 +    setData(blob, data);
 +}
 +
 +void QQmlDataLoader::loadThread(QQmlDataBlob *blob)
 +{
 +    ASSERT_LOADTHREAD();
 +
 +    if (blob->m_url.isEmpty()) {
 +        QQmlError error;
 +        error.setDescription(QLatin1String("Invalid null URL"));
 +        blob->setError(error);
 +        return;
 +    }
 +
 +    QString lf = QQmlEnginePrivate::urlToLocalFileOrQrc(blob->m_url);
 +
 +    if (!lf.isEmpty()) {
 +        if (!QQml_isFileCaseCorrect(lf)) {
 +            QQmlError error;
 +            error.setUrl(blob->m_url);
 +            error.setDescription(QLatin1String("File name case mismatch"));
 +            blob->setError(error);
 +            return;
 +        }
 +        QFile file(lf);
 +        if (file.open(QFile::ReadOnly)) {
 +            QByteArray data = file.readAll();
 +
 +            blob->m_data.setProgress(0xFF);
 +            if (blob->m_data.isAsync())
 +                m_thread->callDownloadProgressChanged(blob, 1.);
 +
 +            setData(blob, data);
 +        } else {
 +            blob->networkError(QNetworkReply::ContentNotFoundError);
 +        }
 +
 +    } else {
 +
 +        QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(blob->m_url));
 +        QObject *nrp = m_thread->networkReplyProxy();
 +        QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), 
 +                         nrp, SLOT(downloadProgress(qint64,qint64)));
 +        QObject::connect(reply, SIGNAL(finished()), 
 +                         nrp, SLOT(finished()));
 +        m_networkReplies.insert(reply, blob);
 +
 +        blob->addref();
 +    }
 +}
 +
 +#define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16
 +
 +void QQmlDataLoader::networkReplyFinished(QNetworkReply *reply)
 +{
 +    Q_ASSERT(m_thread->isThisThread());
 +
 +    reply->deleteLater();
 +
 +    QQmlDataBlob *blob = m_networkReplies.take(reply);
 +
 +    Q_ASSERT(blob);
 +
 +    blob->m_redirectCount++;
 +
 +    if (blob->m_redirectCount < DATALOADER_MAXIMUM_REDIRECT_RECURSION) {
 +        QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
 +        if (redirect.isValid()) {
 +            QUrl url = reply->url().resolved(redirect.toUrl());
 +            blob->m_finalUrl = url;
 +
 +            QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(url));
 +            QObject *nrp = m_thread->networkReplyProxy();
 +            QObject::connect(reply, SIGNAL(finished()), nrp, SLOT(finished()));
 +            m_networkReplies.insert(reply, blob);
 +            return;
 +        }
 +    }
 +
 +    if (reply->error()) {
 +        blob->networkError(reply->error());
 +    } else {
 +        QByteArray data = reply->readAll();
 +        setData(blob, data);
 +    }
 +
 +    blob->release();
 +}
 +
 +void QQmlDataLoader::networkReplyProgress(QNetworkReply *reply,
 +                                                  qint64 bytesReceived, qint64 bytesTotal)
 +{
 +    Q_ASSERT(m_thread->isThisThread());
 +
 +    QQmlDataBlob *blob = m_networkReplies.value(reply);
 +
 +    Q_ASSERT(blob);
 +
 +    if (bytesTotal != 0) {
 +        quint8 progress = 0xFF * (qreal(bytesReceived) / qreal(bytesTotal));
 +        blob->m_data.setProgress(progress);
 +        if (blob->m_data.isAsync())
 +            m_thread->callDownloadProgressChanged(blob, blob->m_data.progress());
 +    }
 +}
 +
 +/*!
 +Return the QQmlEngine associated with this loader
 +*/
 +QQmlEngine *QQmlDataLoader::engine() const
 +{
 +    return m_engine;
 +}
 +
 +/*!
 +Call the initializeEngine() method on \a iface.  Used by QQmlImportDatabase to ensure it
 +gets called in the correct thread.
 +*/
 +void QQmlDataLoader::initializeEngine(QQmlExtensionInterface *iface, 
 +                                              const char *uri)
 +{
 +    Q_ASSERT(m_thread->isThisThread() || engine()->thread() == QThread::currentThread());
 +
 +    if (m_thread->isThisThread()) {
 +        m_thread->initializeEngine(iface, uri);
 +    } else {
 +        Q_ASSERT(engine()->thread() == QThread::currentThread());
 +        iface->initializeEngine(engine(), uri);
 +    }
 +}
 +
 +
 +void QQmlDataLoader::setData(QQmlDataBlob *blob, const QByteArray &data)
 +{
 +    blob->m_inCallback = true;
 +
 +    blob->dataReceived(data);
 +
 +    if (!blob->isError() && !blob->isWaiting())
 +        blob->allDependenciesDone();
 +
 +    if (blob->status() != QQmlDataBlob::Error) 
 +        blob->m_data.setStatus(QQmlDataBlob::WaitingForDependencies);
 +
 +    blob->m_inCallback = false;
 +
 +    blob->tryDone();
 +}
 +
 +/*!
 +Constructs a new type loader that uses the given \a engine.
 +*/
 +QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine)
 +: QQmlDataLoader(engine)
 +{
 +}
 +
 +/*!
 +Destroys the type loader, first clearing the cache of any information about
 +loaded files.
 +*/
 +QQmlTypeLoader::~QQmlTypeLoader()
 +{
 +    clearCache();
 +}
 +
 +/*!
 +\enum QQmlTypeLoader::Option
 +
 +This enum defines the options that control the way type data is handled.
 +
 +\value None             The default value, indicating that no other options
 +                        are enabled.
 +\value PreserveParser   The parser used to handle the type data is preserved
 +                        after the data has been parsed.
 +*/
 +
 +/*!
 +Returns a QQmlTypeData for the specified \a url.  The QQmlTypeData may be cached.
 +*/
 +QQmlTypeData *QQmlTypeLoader::get(const QUrl &url)
 +{
 +    Q_ASSERT(!url.isRelative() && 
 +            (QQmlEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || 
 +             !QDir::isRelativePath(QQmlEnginePrivate::urlToLocalFileOrQrc(url))));
 +
 +    lock();
 +    
 +    QQmlTypeData *typeData = m_typeCache.value(url);
 +
 +    if (!typeData) {
 +        typeData = new QQmlTypeData(url, None, this);
 +        m_typeCache.insert(url, typeData);
 +        QQmlDataLoader::load(typeData);
 +    }
 +
 +    typeData->addref();
 +
 +    unlock();
 +
 +    return typeData;
 +}
 +
 +/*!
 +Returns a QQmlTypeData for the given \a data with the provided base \a url.  The 
 +QQmlTypeData will not be cached.
 +
 +The specified \a options control how the loader handles type data.
 +*/
 +QQmlTypeData *QQmlTypeLoader::get(const QByteArray &data, const QUrl &url, Options options)
 +{
 +    lock();
 +
 +    QQmlTypeData *typeData = new QQmlTypeData(url, options, this);
 +    QQmlDataLoader::loadWithStaticData(typeData, data);
 +
 +    unlock();
 +
 +    return typeData;
 +}
 +
 +/*!
 +Return a QQmlScriptBlob for \a url.  The QQmlScriptData may be cached.
 +*/
 +QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &url)
 +{
 +    Q_ASSERT(!url.isRelative() && 
 +            (QQmlEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || 
 +             !QDir::isRelativePath(QQmlEnginePrivate::urlToLocalFileOrQrc(url))));
 +
 +    lock();
 +
 +    QQmlScriptBlob *scriptBlob = m_scriptCache.value(url);
 +
 +    if (!scriptBlob) {
 +        scriptBlob = new QQmlScriptBlob(url, this);
 +        m_scriptCache.insert(url, scriptBlob);
 +        QQmlDataLoader::load(scriptBlob);
 +    }
 +
 +    scriptBlob->addref();
 +
 +    unlock();
 +
 +    return scriptBlob;
 +}
 +
 +/*!
 +Returns a QQmlQmldirData for \a url.  The QQmlQmldirData may be cached.
 +*/
 +QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url)
 +{
 +    Q_ASSERT(!url.isRelative() && 
 +            (QQmlEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || 
 +             !QDir::isRelativePath(QQmlEnginePrivate::urlToLocalFileOrQrc(url))));
 +
 +    lock();
 +
 +    QQmlQmldirData *qmldirData = m_qmldirCache.value(url);
 +
 +    if (!qmldirData) {
 +        qmldirData = new QQmlQmldirData(url);
 +        m_qmldirCache.insert(url, qmldirData);
 +        QQmlDataLoader::load(qmldirData);
 +    }
 +
 +    qmldirData->addref();
 +
 +    unlock();
 +
 +    return qmldirData;
 +}
 +
 +/*!
 +Returns the absolute filename of path via a directory cache for files named
 +"qmldir", "*.qml", "*.js", and plugins.
 +Returns a empty string if the path does not exist.
 +*/
 +QString QQmlTypeLoader::absoluteFilePath(const QString &path)
 +{
 +    if (path.isEmpty())
 +        return QString();
 +    if (path.at(0) == QLatin1Char(':')) {
 +        // qrc resource
 +        QFileInfo fileInfo(path);
 +        return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString();
 +    }
 +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN)
 +    QString lowPath = path.toLower();
 +    int lastSlash = lowPath.lastIndexOf(QLatin1Char('/'));
 +    QString dirPath = lowPath.left(lastSlash);
 +#else
 +    int lastSlash = path.lastIndexOf(QLatin1Char('/'));
 +    QStringRef dirPath(&path, 0, lastSlash);
 +#endif
 +
 +    StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length()));
 +    if (!fileSet) {
 +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN)
 +        QHashedString dirPathString(dirPath);
 +#else
 +        QHashedString dirPathString(dirPath.toString());
 +#endif
 +        StringSet *files = qmlFilesInDirectory(dirPathString);
 +        m_importDirCache.insert(dirPathString, files);
 +        fileSet = m_importDirCache.value(dirPathString);
 +    }
 +    if (!(*fileSet))
 +        return QString();
 +
 +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN)
 +    QString absoluteFilePath = (*fileSet)->contains(QHashedStringRef(lowPath.constData()+lastSlash+1, lowPath.length()-lastSlash-1)) ? path : QString();
 +#else
 +    QString absoluteFilePath = (*fileSet)->contains(QHashedStringRef(path.constData()+lastSlash+1, path.length()-lastSlash-1)) ? path : QString();
 +#endif
 +    if (absoluteFilePath.length() > 2 && absoluteFilePath.at(0) != QLatin1Char('/') && absoluteFilePath.at(1) != QLatin1Char(':'))
 +        absoluteFilePath = QFileInfo(absoluteFilePath).absoluteFilePath();
 +
 +    return absoluteFilePath;
 +}
 +
 +/*!
 +Returns true if the path is a directory via a directory cache.  Cache is
 +shared with absoluteFilePath().
 +*/
 +bool QQmlTypeLoader::directoryExists(const QString &path)
 +{
 +    if (path.isEmpty())
 +        return false;
 +    if (path.at(0) == QLatin1Char(':')) {
 +        // qrc resource
 +        QFileInfo fileInfo(path);
 +        return fileInfo.exists() && fileInfo.isDir();
 +    }
 +
 +    int length = path.length();
 +    if (path.endsWith(QLatin1Char('/')))
 +        --length;
 +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN)
 +    QString dirPath = path.left(length).toLower();
 +#else
 +    QStringRef dirPath(&path, 0, length);
 +#endif
 +
 +    StringSet **fileSet = m_importDirCache.value(QHashedStringRef(dirPath.constData(), dirPath.length()));
 +    if (!fileSet) {
 +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_DARWIN)
 +        QHashedString dirPathString(dirPath);
 +#else
 +        QHashedString dirPathString(dirPath.toString());
 +#endif
 +        StringSet *files = qmlFilesInDirectory(dirPathString);
 +        m_importDirCache.insert(dirPathString, files);
 +        fileSet = m_importDirCache.value(dirPathString);
 +    }
 +
 +    return (*fileSet);
 +}
 +
 +
 +/*!
 +Return a QQmlDirParser for absoluteFilePath.  The QQmlDirParser may be cached.
 +*/
 +const QQmlDirParser *QQmlTypeLoader::qmlDirParser(const QString &absoluteFilePath)
 +{
 +    QQmlDirParser *qmldirParser;
 +    QQmlDirParser **val = m_importQmlDirCache.value(absoluteFilePath);
 +    if (!val) {
 +        qmldirParser = new QQmlDirParser;
 +        qmldirParser->setFileSource(absoluteFilePath);
 +        qmldirParser->setUrl(QUrl::fromLocalFile(absoluteFilePath));
 +        qmldirParser->parse();
 +        m_importQmlDirCache.insert(absoluteFilePath, qmldirParser);
 +    } else {
 +        qmldirParser = *val;
 +    }
 +
 +    return qmldirParser;
 +}
 +
 +
 +/*!
 +Clears cached information about loaded files, including any type data, scripts
 +and qmldir information.
 +*/
 +void QQmlTypeLoader::clearCache()
 +{
 +    for (TypeCache::Iterator iter = m_typeCache.begin(); iter != m_typeCache.end(); ++iter) 
 +        (*iter)->release();
 +    for (ScriptCache::Iterator iter = m_scriptCache.begin(); iter != m_scriptCache.end(); ++iter) 
 +        (*iter)->release();
 +    for (QmldirCache::Iterator iter = m_qmldirCache.begin(); iter != m_qmldirCache.end(); ++iter) 
 +        (*iter)->release();
 +    qDeleteAll(m_importDirCache);
 +    qDeleteAll(m_importQmlDirCache);
 +
 +    m_typeCache.clear();
 +    m_scriptCache.clear();
 +    m_qmldirCache.clear();
 +    m_importDirCache.clear();
 +    m_importQmlDirCache.clear();
 +}
 +
 +
 +QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader::Options options, 
 +                                           QQmlTypeLoader *manager)
 +: QQmlDataBlob(url, QmlFile), m_options(options), m_imports(manager), m_typesResolved(false),
 +   m_compiledData(0), m_typeLoader(manager)
 +{
 +}
 +
 +QQmlTypeData::~QQmlTypeData()
 +{
 +    for (int ii = 0; ii < m_scripts.count(); ++ii) 
 +        m_scripts.at(ii).script->release();
 +    for (int ii = 0; ii < m_qmldirs.count(); ++ii) 
 +        m_qmldirs.at(ii)->release();
 +    for (int ii = 0; ii < m_types.count(); ++ii) 
 +        if (m_types.at(ii).typeData) m_types.at(ii).typeData->release();
 +    if (m_compiledData)
 +        m_compiledData->release();
 +}
 +
 +QQmlTypeLoader *QQmlTypeData::typeLoader() const
 +{
 +    return m_typeLoader;
 +}
 +
 +const QQmlImports &QQmlTypeData::imports() const
 +{
 +    return m_imports;
 +}
 +
 +const QQmlScript::Parser &QQmlTypeData::parser() const
 +{
 +    return scriptParser;
 +}
 +
 +const QList<QQmlTypeData::TypeReference> &QQmlTypeData::resolvedTypes() const
 +{
 +    return m_types;
 +}
 +
 +const QList<QQmlTypeData::ScriptReference> &QQmlTypeData::resolvedScripts() const
 +{
 +    return m_scripts;
 +}
 +
 +const QSet<QString> &QQmlTypeData::namespaces() const
 +{
 +    return m_namespaces;
 +}
 +
 +QQmlCompiledData *QQmlTypeData::compiledData() const
 +{
 +    if (m_compiledData) 
 +        m_compiledData->addref();
 +
 +    return m_compiledData;
 +}
 +
 +void QQmlTypeData::registerCallback(TypeDataCallback *callback)
 +{
 +    Q_ASSERT(!m_callbacks.contains(callback));
 +    m_callbacks.append(callback);
 +}
 +
 +void QQmlTypeData::unregisterCallback(TypeDataCallback *callback)
 +{
 +    Q_ASSERT(m_callbacks.contains(callback));
 +    m_callbacks.removeOne(callback);
 +    Q_ASSERT(!m_callbacks.contains(callback));
 +}
 +
 +void QQmlTypeData::done()
 +{
 +    // Check all script dependencies for errors
 +    for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
 +        const ScriptReference &script = m_scripts.at(ii);
 +        Q_ASSERT(script.script->isCompleteOrError());
 +        if (script.script->isError()) {
 +            QList<QQmlError> errors = script.script->errors();
 +            QQmlError error;
 +            error.setUrl(finalUrl());
 +            error.setLine(script.location.line);
 +            error.setColumn(script.location.column);
 +            error.setDescription(QQmlTypeLoader::tr("Script %1 unavailable").arg(script.script->url().toString()));
 +            errors.prepend(error);
 +            setError(errors);
 +        }
 +    }
 +
 +    // Check all type dependencies for errors
 +    for (int ii = 0; !isError() && ii < m_types.count(); ++ii) {
 +        const TypeReference &type = m_types.at(ii);
 +        Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError());
 +        if (type.typeData && type.typeData->isError()) {
 +            QString typeName = scriptParser.referencedTypes().at(ii)->name;
 +
 +            QList<QQmlError> errors = type.typeData->errors();
 +            QQmlError error;
 +            error.setUrl(finalUrl());
 +            error.setLine(type.location.line);
 +            error.setColumn(type.location.column);
 +            error.setDescription(QQmlTypeLoader::tr("Type %1 unavailable").arg(typeName));
 +            errors.prepend(error);
 +            setError(errors);
 +        }
 +    }
 +
 +    // Compile component
 +    if (!isError()) 
 +        compile();
 +
 +    if (!(m_options & QQmlTypeLoader::PreserveParser))
 +        scriptParser.clear();
 +}
 +
 +void QQmlTypeData::completed()
 +{
 +    // Notify callbacks
 +    while (!m_callbacks.isEmpty()) {
 +        TypeDataCallback *callback = m_callbacks.takeFirst();
 +        callback->typeDataReady(this);
 +    }
 +}
 +
 +void QQmlTypeData::dataReceived(const QByteArray &data)
 +{
 +    if (!scriptParser.parse(data, finalUrl(), finalUrlString())) {
 +        setError(scriptParser.errors());
 +        return;
 +    }
 +
 +    m_imports.setBaseUrl(finalUrl(), finalUrlString());
 +
 +    foreach (const QQmlScript::Import &import, scriptParser.imports()) {
 +        if (import.type == QQmlScript::Import::File && import.qualifier.isEmpty()) {
 +            QUrl importUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir")));
 +            if (QQmlEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) {
 +                QQmlQmldirData *data = typeLoader()->getQmldir(importUrl);
 +                addDependency(data);
 +                m_qmldirs << data;
 +            }
 +        } else if (import.type == QQmlScript::Import::Script) {
 +            QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri));
 +            QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
 +            addDependency(blob);
 +
 +            ScriptReference ref;
 +            ref.location = import.location.start;
 +            ref.qualifier = import.qualifier;
 +            ref.script = blob;
 +            m_scripts << ref;
 +
 +        }
 +    }
 +
 +    if (!finalUrl().scheme().isEmpty()) {
 +        QUrl importUrl = finalUrl().resolved(QUrl(QLatin1String("qmldir")));
 +        if (QQmlEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) {
 +            QQmlQmldirData *data = typeLoader()->getQmldir(importUrl);
 +            addDependency(data);
 +            m_qmldirs << data;
 +        }
 +    }
 +}
 +
 +void QQmlTypeData::allDependenciesDone()
 +{
 +    if (!m_typesResolved) {
 +        resolveTypes();
 +        m_typesResolved = true;
 +    }
 +}
 +
 +void QQmlTypeData::downloadProgressChanged(qreal p)
 +{
 +    for (int ii = 0; ii < m_callbacks.count(); ++ii) {
 +        TypeDataCallback *callback = m_callbacks.at(ii);
 +        callback->typeDataProgress(this, p);
 +    }
 +}
 +
 +void QQmlTypeData::compile()
 +{
 +    Q_ASSERT(m_compiledData == 0);
-     QQmlProfilerService::rangeLocation(QQmlProfilerService::Compiling, QUrl(m_compiledData->name),1,1);
-     QQmlProfilerService::rangeData(QQmlProfilerService::Compiling, m_compiledData->name);
 +
 +    m_compiledData = new QQmlCompiledData(typeLoader()->engine());
 +    m_compiledData->url = finalUrl();
 +    m_compiledData->name = finalUrlString();
-     QQmlProfilerService::endRange(QQmlProfilerService::Compiling);
++
++    QQmlCompilingProfiler prof(m_compiledData->name);
 +
 +    QQmlCompiler compiler(&scriptParser._pool);
 +    if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) {
 +        setError(compiler.errors());
 +        m_compiledData->release();
 +        m_compiledData = 0;
 +    }
 +}
 +
 +void QQmlTypeData::resolveTypes()
 +{
 +    QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_typeLoader->engine());
 +    QQmlImportDatabase *importDatabase = &ep->importDatabase;
 +
 +    // For local urls, add an implicit import "." as first (most overridden) lookup. 
 +    // This will also trigger the loading of the qmldir and the import of any native 
 +    // types from available plugins.
 +    QList<QQmlError> errors;
 +    if (QQmlQmldirData *qmldir = qmldirForUrl(finalUrl().resolved(QUrl(QLatin1String("./qmldir"))))) {
 +        m_imports.addImport(importDatabase, QLatin1String("."),
 +                            QString(), -1, -1, QQmlScript::Import::File, 
 +                            qmldir->dirComponents(), &errors);
 +    } else {
 +        m_imports.addImport(importDatabase, QLatin1String("."), 
 +                            QString(), -1, -1, QQmlScript::Import::File, 
 +                            QQmlDirComponents(), &errors);
 +    }
 +
 +    // remove any errors which are due to the implicit import which aren't real errors.
 +    // for example, if the implicitly included qmldir file doesn't exist, that is not an error.
 +    QList<QQmlError> realErrors;
 +    for (int i = 0; i < errors.size(); ++i) {
 +        if (errors.at(i).description() != QQmlImportDatabase::tr("import \".\" has no qmldir and no namespace")
 +                && errors.at(i).description() != QQmlImportDatabase::tr("\".\": no such directory")) {
 +            realErrors.prepend(errors.at(i)); // this is a real error.
 +        }
 +    }
 +
 +    // report any real errors which occurred during plugin loading or qmldir parsing.
 +    if (!realErrors.isEmpty()) {
 +        setError(realErrors);
 +        return;
 +    }
 +
 +    foreach (const QQmlScript::Import &import, scriptParser.imports()) {
 +        QQmlDirComponents qmldircomponentsnetwork;
 +        if (import.type == QQmlScript::Import::Script)
 +            continue;
 +
 +        if (import.type == QQmlScript::Import::File && import.qualifier.isEmpty()) {
 +            QUrl qmldirUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir")));
 +            if (QQmlQmldirData *qmldir = qmldirForUrl(qmldirUrl))
 +                qmldircomponentsnetwork = qmldir->dirComponents();
 +        }
 +
 +        int vmaj = -1;
 +        int vmin = -1;
 +        import.extractVersion(&vmaj, &vmin);
 +
 +        QList<QQmlError> errors;
 +        if (!m_imports.addImport(importDatabase, import.uri, import.qualifier,
 +                                 vmaj, vmin, import.type, qmldircomponentsnetwork, &errors)) {
 +            QQmlError error;
 +            if (errors.size()) {
 +                error = errors.takeFirst();
 +            } else {
 +                // this should not be possible!
 +                // Description should come from error provided by addImport() function.
 +                error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database"));
 +            }
 +            error.setUrl(m_imports.baseUrl());
 +            error.setLine(import.location.start.line);
 +            error.setColumn(import.location.start.column);
 +            errors.prepend(error); // put it back on the list after filling out information.
 +
 +            setError(errors);
 +            return;
 +        }
 +    }
 +
 +    // Add any imported scripts to our resolved set
 +    foreach (const QQmlImports::ScriptReference &script, m_imports.resolvedScripts())
 +    {
 +        QQmlScriptBlob *blob = typeLoader()->getScript(script.location);
 +        addDependency(blob);
 +
 +        ScriptReference ref;
 +        //ref.location = ...
 +        ref.qualifier = script.nameSpace;
 +        if (!script.qualifier.isEmpty())
 +        {
 +            ref.qualifier.prepend(script.qualifier + QLatin1Char('.'));
 +
 +            // Add a reference to the enclosing namespace
 +            m_namespaces.insert(script.qualifier);
 +        }
 +
 +        ref.script = blob;
 +        m_scripts << ref;
 +    }
 +
 +    foreach (QQmlScript::TypeReference *parserRef, scriptParser.referencedTypes()) {
 +        TypeReference ref;
 +
 +        QString url;
 +        int majorVersion;
 +        int minorVersion;
 +        QQmlImportedNamespace *typeNamespace = 0;
 +        QList<QQmlError> errors;
 +
 +        if (!m_imports.resolveType(parserRef->name, &ref.type, &url, &majorVersion, &minorVersion,
 +                                   &typeNamespace, &errors) || typeNamespace) {
 +            // Known to not be a type:
 +            //  - known to be a namespace (Namespace {})
 +            //  - type with unknown namespace (UnknownNamespace.SomeType {})
 +            QQmlError error;
 +            QString userTypeName = parserRef->name;
 +            userTypeName.replace(QLatin1Char('/'),QLatin1Char('.'));
 +            if (typeNamespace) {
 +                error.setDescription(QQmlTypeLoader::tr("Namespace %1 cannot be used as a type").arg(userTypeName));
 +            } else {
 +                if (errors.size()) {
 +                    error = errors.takeFirst();
 +                } else {
 +                    // this should not be possible!
 +                    // Description should come from error provided by addImport() function.
 +                    error.setDescription(QQmlTypeLoader::tr("Unreported error adding script import to import database"));
 +                }
 +                error.setUrl(m_imports.baseUrl());
 +                error.setDescription(QQmlTypeLoader::tr("%1 %2").arg(userTypeName).arg(error.description()));
 +            }
 +
 +            if (!parserRef->refObjects.isEmpty()) {
 +                QQmlScript::Object *obj = parserRef->refObjects.first();
 +                error.setLine(obj->location.start.line);
 +                error.setColumn(obj->location.start.column);
 +            }
 +
 +            errors.prepend(error);
 +            setError(errors);
 +            return;
 +        }
 +
 +        if (ref.type) {
 +            ref.majorVersion = majorVersion;
 +            ref.minorVersion = minorVersion;
 +        } else {
 +            ref.typeData = typeLoader()->get(QUrl(url));
 +            addDependency(ref.typeData);
 +        }
 +
 +        if (parserRef->refObjects.count())
 +            ref.location = parserRef->refObjects.first()->location.start;
 +
 +        m_types << ref;
 +    }
 +}
 +
 +QQmlQmldirData *QQmlTypeData::qmldirForUrl(const QUrl &url)
 +{
 +    for (int ii = 0; ii < m_qmldirs.count(); ++ii) {
 +        if (m_qmldirs.at(ii)->url() == url)
 +            return m_qmldirs.at(ii);
 +    }
 +    return 0;
 +}
 +
 +QQmlScriptData::QQmlScriptData()
 +: importCache(0), pragmas(QQmlScript::Object::ScriptBlock::None), m_loaded(false) 
 +{
 +}
 +
 +QQmlScriptData::~QQmlScriptData()
 +{
 +}
 +
 +void QQmlScriptData::clear()
 +{
 +    if (importCache) {
 +        importCache->release();
 +        importCache = 0;
 +    }
 +
 +    for (int ii = 0; ii < scripts.count(); ++ii)
 +        scripts.at(ii)->release();
 +    scripts.clear();
 +
 +    qPersistentDispose(m_program);
 +    qPersistentDispose(m_value);
 +
 +    // An addref() was made when the QQmlCleanup was added to the engine.
 +    release();
 +}
 +
 +QQmlScriptBlob::QQmlScriptBlob(const QUrl &url, QQmlTypeLoader *loader)
 +: QQmlDataBlob(url, JavaScriptFile), m_pragmas(QQmlScript::Object::ScriptBlock::None),
 +  m_imports(loader), m_scriptData(0), m_typeLoader(loader)
 +{
 +}
 +
 +QQmlScriptBlob::~QQmlScriptBlob()
 +{
 +    if (m_scriptData) {
 +        m_scriptData->release();
 +        m_scriptData = 0;
 +    }
 +}
 +
 +QQmlScript::Object::ScriptBlock::Pragmas QQmlScriptBlob::pragmas() const
 +{
 +    return m_pragmas;
 +}
 +
 +QQmlTypeLoader *QQmlScriptBlob::typeLoader() const
 +{
 +    return m_typeLoader;
 +}
 +
 +const QQmlImports &QQmlScriptBlob::imports() const
 +{
 +    return m_imports;
 +}
 +
 +QQmlScriptData *QQmlScriptBlob::scriptData() const
 +{
 +    return m_scriptData;
 +}
 +
 +void QQmlScriptBlob::dataReceived(const QByteArray &data)
 +{
 +    QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_typeLoader->engine());
 +    QQmlImportDatabase *importDatabase = &ep->importDatabase;
 +
 +    m_source = QString::fromUtf8(data);
 +
 +    QQmlScript::Parser::JavaScriptMetaData metadata =
 +        QQmlScript::Parser::extractMetaData(m_source);
 +
 +    m_imports.setBaseUrl(finalUrl(), finalUrlString());
 +
 +    m_pragmas = metadata.pragmas;
 +
 +    foreach (const QQmlScript::Import &import, metadata.imports) {
 +        Q_ASSERT(import.type != QQmlScript::Import::File);
 +
 +        if (import.type == QQmlScript::Import::Script) {
 +            QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri));
 +            QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
 +            addDependency(blob);
 +
 +            ScriptReference ref;
 +            ref.location = import.location.start;
 +            ref.qualifier = import.qualifier;
 +            ref.script = blob;
 +            m_scripts << ref;
 +        } else {
 +            Q_ASSERT(import.type == QQmlScript::Import::Library);
 +            int vmaj = -1;
 +            int vmin = -1;
 +            import.extractVersion(&vmaj, &vmin);
 +
 +            QList<QQmlError> errors;
 +            if (!m_imports.addImport(importDatabase, import.uri, import.qualifier, vmaj, vmin,
 +                                     import.type, QQmlDirComponents(), &errors)) {
 +                QQmlError error = errors.takeFirst();
 +                // description should be set by addImport().
 +                error.setUrl(m_imports.baseUrl());
 +                error.setLine(import.location.start.line);
 +                error.setColumn(import.location.start.column);
 +                errors.prepend(error);
 +
 +                setError(errors);
 +                return;
 +            }
 +        }
 +    }
 +}
 +
 +void QQmlScriptBlob::done()
 +{
 +    // Check all script dependencies for errors
 +    for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
 +        const ScriptReference &script = m_scripts.at(ii);
 +        Q_ASSERT(script.script->isCompleteOrError());
 +        if (script.script->isError()) {
 +            QList<QQmlError> errors = script.script->errors();
 +            QQmlError error;
 +            error.setUrl(finalUrl());
 +            error.setLine(script.location.line);
 +            error.setColumn(script.location.column);
 +            error.setDescription(typeLoader()->tr("Script %1 unavailable").arg(script.script->url().toString()));
 +            errors.prepend(error);
 +            setError(errors);
 +        }
 +    }
 +
 +    if (isError())
 +        return;
 +
 +    QQmlEngine *engine = typeLoader()->engine();
 +    m_scriptData = new QQmlScriptData();
 +    m_scriptData->url = finalUrl();
 +    m_scriptData->urlString = finalUrlString();
 +    m_scriptData->importCache = new QQmlTypeNameCache();
 +
 +    for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) {
 +        const ScriptReference &script = m_scripts.at(ii);
 +
 +        m_scriptData->scripts.append(script.script);
 +        m_scriptData->importCache->add(script.qualifier, ii);
 +    }
 +
 +    m_imports.populateCache(m_scriptData->importCache, engine);
 +
 +    m_scriptData->pragmas = m_pragmas;
 +    m_scriptData->m_programSource = m_source.toUtf8();
 +    m_source.clear();
 +}
 +
 +QQmlQmldirData::QQmlQmldirData(const QUrl &url)
 +: QQmlDataBlob(url, QmldirFile)
 +{
 +}
 +
 +const QQmlDirComponents &QQmlQmldirData::dirComponents() const
 +{
 +    return m_components;
 +}
 +
 +void QQmlQmldirData::dataReceived(const QByteArray &data)
 +{
 +    QQmlDirParser parser;
 +    parser.setSource(QString::fromUtf8(data));
 +    parser.parse();
 +    m_components = parser.components();
 +}
 +
 +QT_END_NAMESPACE
 +
 +#include "qqmltypeloader.moc"
index 8c8d4d0,0000000..844f2cc
mode 100644,000000..100644
--- /dev/null
@@@ -1,240 -1,0 +1,238 @@@
-         inline Interrupt(bool *runWhile);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLVME_P_H
 +#define QQMLVME_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 "qqmlerror.h"
 +#include <private/qbitfield_p.h>
 +#include "qqmlinstruction_p.h"
 +#include <private/qrecursionwatcher_p.h>
 +
 +#include <QtCore/QStack>
 +#include <QtCore/QString>
 +#include <QtCore/qelapsedtimer.h>
 +#include <QtCore/qcoreapplication.h>
 +
 +#include <private/qv8_p.h>
 +#include <private/qqmlengine_p.h>
 +#include <private/qfinitestack_p.h>
 +
 +#include <private/qqmltrace_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QObject;
 +class QJSValue;
 +class QQmlScriptData;
 +class QQmlCompiledData;
 +class QQmlCompiledData;
 +class QQmlContextData;
 +
 +namespace QQmlVMETypes {
 +    struct List
 +    {
 +        List() : type(0) {}
 +        List(int t) : type(t) {}
 +
 +        int type;
 +        QQmlListProperty<void> qListProperty;
 +    };
 +}
 +Q_DECLARE_TYPEINFO(QQmlVMETypes::List, Q_PRIMITIVE_TYPE  | Q_MOVABLE_TYPE);
 +
 +class QQmlVME
 +{
 +    Q_DECLARE_TR_FUNCTIONS(QQmlVME)
 +public:
 +    class Interrupt {
 +    public:
 +        inline Interrupt();
-         union {
-             struct {
-                 QElapsedTimer timer;
-                 int nsecs;
-             };
-             bool *runWhile;
++        inline Interrupt(volatile bool *runWhile, int nsecs=0);
 +        inline Interrupt(int nsecs);
 +
 +        inline void reset();
 +        inline bool shouldInterrupt() const;
 +    private:
 +        enum Mode { None, Time, Flag };
 +        Mode mode;
- : mode(None)
++        struct {
++            QElapsedTimer timer;
++            int nsecs;
 +        };
++        volatile bool *runWhile;
 +    };
 +
 +    QQmlVME() : data(0), componentAttached(0) {}
 +    QQmlVME(void *data) : data(data), componentAttached(0) {}
 +
 +    void *data;
 +    QQmlComponentAttached *componentAttached;
 +    QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks;
 +
 +    void init(QQmlContextData *, QQmlCompiledData *, int start,
 +              QQmlContextData * = 0);
 +    bool initDeferred(QObject *);
 +    void reset();
 +
 +    QObject *execute(QList<QQmlError> *errors, const Interrupt & = Interrupt());
 +    QQmlContextData *complete(const Interrupt & = Interrupt());
 +
 +private:
 +    friend class QQmlVMEGuard;
 +
 +    QObject *run(QList<QQmlError> *errors, const Interrupt &
 +#ifdef QML_THREADED_VME_INTERPRETER
 +                 , void ***storeJumpTable = 0
 +#endif
 +                );
 +    v8::Persistent<v8::Object> run(QQmlContextData *, QQmlScriptData *);
 +
 +#ifdef QML_THREADED_VME_INTERPRETER
 +    static void **instructionJumpTable();
 +    friend class QQmlCompiledData;
 +#endif
 +
 +    QQmlEngine *engine;
 +    QRecursionNode recursion;
 +
 +#ifdef QML_ENABLE_TRACE
 +    QQmlCompiledData *rootComponent;
 +#endif
 +
 +    QFiniteStack<QObject *> objects;
 +    QFiniteStack<QQmlVMETypes::List> lists;
 +
 +    QFiniteStack<QQmlAbstractBinding *> bindValues;
 +    QFiniteStack<QQmlParserStatus *> parserStatus;
 +#ifdef QML_ENABLE_TRACE
 +    QFiniteStack<QQmlData *> parserStatusData;
 +#endif
 +
 +    QQmlGuardedContextData rootContext;
 +    QQmlGuardedContextData creationContext;
 +
 +    struct State {
 +        enum Flag { Deferred = 0x00000001 };
 +
 +        State() : flags(0), context(0), compiledData(0), instructionStream(0) {}
 +        quint32 flags;
 +        QQmlContextData *context;
 +        QQmlCompiledData *compiledData;
 +        const char *instructionStream;
 +        QBitField bindingSkipList;
 +    };
 +
 +    QStack<State> states;
 +
 +    static void blank(QFiniteStack<QQmlParserStatus *> &);
 +    static void blank(QFiniteStack<QQmlAbstractBinding *> &);
 +};
 +
 +// Used to check that a QQmlVME that is interrupted mid-execution
 +// is still valid.  Checks all the objects and contexts have not been 
 +// deleted.
 +class QQmlVMEGuard
 +{
 +public:
 +    QQmlVMEGuard();
 +    ~QQmlVMEGuard();
 +
 +    void guard(QQmlVME *);
 +    void clear();
 +
 +    bool isOK() const;
 +
 +private:
 +    int m_objectCount;
 +    QQmlGuard<QObject> *m_objects;
 +    int m_contextCount;
 +    QQmlGuardedContextData *m_contexts;
 +};
 +
 +QQmlVME::Interrupt::Interrupt()
- QQmlVME::Interrupt::Interrupt(bool *runWhile)
- : mode(Flag), runWhile(runWhile)
++    : mode(None), nsecs(0), runWhile(0)
 +{
 +}
 +
- : mode(Time), nsecs(nsecs)
++QQmlVME::Interrupt::Interrupt(volatile bool *runWhile, int nsecs)
++    : mode(Flag), nsecs(nsecs), runWhile(runWhile)
 +{
 +}
 +
 +QQmlVME::Interrupt::Interrupt(int nsecs)
-     if (mode == Time) 
++    : mode(Time), nsecs(nsecs), runWhile(0)
 +{
 +}
 +
 +void QQmlVME::Interrupt::reset()
 +{
-         return !*runWhile;
++    if (mode == Time || nsecs)
 +        timer.start();
 +}
 +
 +bool QQmlVME::Interrupt::shouldInterrupt() const
 +{
 +    if (mode == None) {
 +        return false;
 +    } else if (mode == Time) {
 +        return timer.nsecsElapsed() > nsecs;
 +    } else if (mode == Flag) {
++        return !*runWhile || (nsecs && timer.nsecsElapsed() > nsecs);
 +    } else {
 +        return false;
 +    }
 +}
 +
 +QT_END_NAMESPACE
 +
 +#endif // QQMLVME_P_H
index f91aa28,0000000..529f181
mode 100644,000000..100644
--- /dev/null
@@@ -1,730 -1,0 +1,730 @@@
-     initDeclarativeGlobalObject();
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qquickworkerscript_p.h"
 +#include "qquicklistmodel_p.h"
 +#include "qquicklistmodelworkeragent_p.h"
 +#include "qqmlengine_p.h"
 +#include "qqmlexpression_p.h"
 +
 +#include <QtCore/qcoreevent.h>
 +#include <QtCore/qcoreapplication.h>
 +#include <QtCore/qdebug.h>
 +#include <QtQml/qjsengine.h>
 +#include <QtCore/qmutex.h>
 +#include <QtCore/qwaitcondition.h>
 +#include <QtCore/qfile.h>
 +#include <QtCore/qdatetime.h>
 +#include <QtNetwork/qnetworkaccessmanager.h>
 +#include <QtQml/qqmlinfo.h>
 +#include "qqmlnetworkaccessmanagerfactory.h"
 +
 +#include <private/qv8engine_p.h>
 +#include <private/qv8worker_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class WorkerDataEvent : public QEvent
 +{
 +public:
 +    enum Type { WorkerData = QEvent::User };
 +
 +    WorkerDataEvent(int workerId, const QByteArray &data);
 +    virtual ~WorkerDataEvent();
 +
 +    int workerId() const;
 +    QByteArray data() const;
 +
 +private:
 +    int m_id;
 +    QByteArray m_data;
 +};
 +
 +class WorkerLoadEvent : public QEvent
 +{
 +public:
 +    enum Type { WorkerLoad = WorkerDataEvent::WorkerData + 1 };
 +
 +    WorkerLoadEvent(int workerId, const QUrl &url);
 +
 +    int workerId() const;
 +    QUrl url() const;
 +
 +private:
 +    int m_id;
 +    QUrl m_url;
 +};
 +
 +class WorkerRemoveEvent : public QEvent
 +{
 +public:
 +    enum Type { WorkerRemove = WorkerLoadEvent::WorkerLoad + 1 };
 +
 +    WorkerRemoveEvent(int workerId);
 +
 +    int workerId() const;
 +
 +private:
 +    int m_id;
 +};
 +
 +class WorkerErrorEvent : public QEvent
 +{
 +public:
 +    enum Type { WorkerError = WorkerRemoveEvent::WorkerRemove + 1 };
 +
 +    WorkerErrorEvent(const QQmlError &error);
 +
 +    QQmlError error() const;
 +
 +private:
 +    QQmlError m_error;
 +};
 +
 +class QQuickWorkerScriptEnginePrivate : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    enum WorkerEventTypes {
 +        WorkerDestroyEvent = QEvent::User + 100
 +    };
 +
 +    QQuickWorkerScriptEnginePrivate(QQmlEngine *eng);
 +
 +    class WorkerEngine : public QV8Engine
 +    {
 +    public:
 +        WorkerEngine(QQuickWorkerScriptEnginePrivate *parent);
 +        ~WorkerEngine();
 +
 +        void init();
 +        virtual QNetworkAccessManager *networkAccessManager();
 +
 +        QQuickWorkerScriptEnginePrivate *p;
 +
 +        v8::Local<v8::Function> sendFunction(int id);
 +        void callOnMessage(v8::Handle<v8::Object> object, v8::Handle<v8::Value> arg);
 +    private:
 +        v8::Persistent<v8::Function> onmessage;
 +        v8::Persistent<v8::Function> createsend;
 +        QNetworkAccessManager *accessManager;
 +    };
 +
 +    WorkerEngine *workerEngine;
 +    static QQuickWorkerScriptEnginePrivate *get(QV8Engine *e) {
 +        return static_cast<WorkerEngine *>(e)->p;
 +    }
 +
 +    QQmlEngine *qmlengine;
 +
 +    QMutex m_lock;
 +    QWaitCondition m_wait;
 +
 +    struct WorkerScript {
 +        WorkerScript();
 +        ~WorkerScript();
 +
 +        int id;
 +        QUrl source;
 +        bool initialized;
 +        QQuickWorkerScript *owner;
 +        v8::Persistent<v8::Object> object;
 +    };
 +
 +    QHash<int, WorkerScript *> workers;
 +    v8::Handle<v8::Object> getWorker(WorkerScript *);
 +
 +    int m_nextId;
 +
 +    static v8::Handle<v8::Value> sendMessage(const v8::Arguments &args);
 +
 +signals:
 +    void stopThread();
 +
 +protected:
 +    virtual bool event(QEvent *);
 +
 +private:
 +    void processMessage(int, const QByteArray &);
 +    void processLoad(int, const QUrl &);
 +    void reportScriptException(WorkerScript *, const QQmlError &error);
 +};
 +
 +QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent) 
 +: QV8Engine(0), p(parent), accessManager(0)
 +{
 +}
 +
 +QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine() 
 +{ 
 +    qPersistentDispose(createsend);
 +    qPersistentDispose(onmessage);
 +    delete accessManager; 
 +}
 +
 +void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
 +{
++    initQmlGlobalObject();
 +#define CALL_ONMESSAGE_SCRIPT \
 +    "(function(object, message) { "\
 +        "var isfunction = false; "\
 +        "try { "\
 +            "isfunction = object.WorkerScript.onMessage instanceof Function; "\
 +        "} catch (e) {}" \
 +        "if (isfunction) "\
 +            "object.WorkerScript.onMessage(message); "\
 +    "})"
 +
 +#define SEND_MESSAGE_CREATE_SCRIPT \
 +    "(function(method, engine) { "\
 +        "return (function(id) { "\
 +            "return (function(message) { "\
 +                "if (arguments.length) method(engine, id, message); "\
 +            "}); "\
 +        "}); "\
 +    "})"
 +
 +    v8::HandleScope handle_scope;
 +    v8::Context::Scope scope(context());
 +
 +    {
 +    v8::Local<v8::Script> onmessagescript = v8::Script::New(v8::String::New(CALL_ONMESSAGE_SCRIPT));
 +    onmessage = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(onmessagescript->Run()));
 +    }
 +    {
 +    v8::Local<v8::Script> createsendscript = v8::Script::New(v8::String::New(SEND_MESSAGE_CREATE_SCRIPT));
 +    v8::Local<v8::Function> createsendconstructor = v8::Local<v8::Function>::Cast(createsendscript->Run());
 +
 +    v8::Handle<v8::Value> args[] = { 
 +        V8FUNCTION(QQuickWorkerScriptEnginePrivate::sendMessage, this)
 +    };
 +    v8::Local<v8::Value> createsendvalue = createsendconstructor->Call(global(), 1, args);
 +    
 +    createsend = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(createsendvalue));
 +    }
 +}
 +
 +// Requires handle and context scope
 +v8::Local<v8::Function> QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id)
 +{
 +    v8::Handle<v8::Value> args[] = { v8::Integer::New(id) };
 +    return v8::Local<v8::Function>::Cast(createsend->Call(global(), 1, args));
 +}
 +
 +// Requires handle and context scope
 +void QQuickWorkerScriptEnginePrivate::WorkerEngine::callOnMessage(v8::Handle<v8::Object> object, 
 +                                                                        v8::Handle<v8::Value> arg)
 +{
 +    v8::Handle<v8::Value> args[] = { object, arg };
 +    onmessage->Call(global(), 2, args);
 +}
 +
 +QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager() 
 +{
 +    if (!accessManager) {
 +        if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
 +            accessManager = p->qmlengine->networkAccessManagerFactory()->create(p);
 +        } else {
 +            accessManager = new QNetworkAccessManager(p);
 +        }
 +    }
 +    return accessManager;
 +}
 +
 +QQuickWorkerScriptEnginePrivate::QQuickWorkerScriptEnginePrivate(QQmlEngine *engine)
 +: workerEngine(0), qmlengine(engine), m_nextId(0)
 +{
 +}
 +
 +v8::Handle<v8::Value> QQuickWorkerScriptEnginePrivate::sendMessage(const v8::Arguments &args)
 +{
 +    WorkerEngine *engine = (WorkerEngine*)V8ENGINE();
 +
 +    int id = args[1]->Int32Value();
 +
 +    QByteArray data = QV8Worker::serialize(args[2], engine);
 +
 +    QMutexLocker(&engine->p->m_lock);
 +    WorkerScript *script = engine->p->workers.value(id);
 +    if (!script)
 +        return v8::Undefined();
 +
 +    if (script->owner)
 +        QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, data));
 +
 +    return v8::Undefined();
 +}
 +
 +// Requires handle scope and context scope
 +v8::Handle<v8::Object> QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script)
 +{
 +    if (!script->initialized) {
 +        script->initialized = true;
 +
 +        script->object = qPersistentNew<v8::Object>(workerEngine->contextWrapper()->urlScope(script->source));
 +
 +        workerEngine->contextWrapper()->setReadOnly(script->object, false);
 +
 +        v8::Local<v8::Object> api = v8::Object::New();
 +        api->Set(v8::String::New("sendMessage"), workerEngine->sendFunction(script->id));
 +
 +        script->object->Set(v8::String::New("WorkerScript"), api);
 +
 +        workerEngine->contextWrapper()->setReadOnly(script->object, true);
 +    }
 +
 +    return script->object;
 +}
 +
 +bool QQuickWorkerScriptEnginePrivate::event(QEvent *event)
 +{
 +    if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
 +        WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
 +        processMessage(workerEvent->workerId(), workerEvent->data());
 +        return true;
 +    } else if (event->type() == (QEvent::Type)WorkerLoadEvent::WorkerLoad) {
 +        WorkerLoadEvent *workerEvent = static_cast<WorkerLoadEvent *>(event);
 +        processLoad(workerEvent->workerId(), workerEvent->url());
 +        return true;
 +    } else if (event->type() == (QEvent::Type)WorkerDestroyEvent) {
 +        emit stopThread();
 +        return true;
 +    } else if (event->type() == (QEvent::Type)WorkerRemoveEvent::WorkerRemove) {
 +        WorkerRemoveEvent *workerEvent = static_cast<WorkerRemoveEvent *>(event);
 +        workers.remove(workerEvent->workerId());
 +        return true;
 +    } else {
 +        return QObject::event(event);
 +    }
 +}
 +
 +void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &data)
 +{
 +    WorkerScript *script = workers.value(id);
 +    if (!script)
 +        return;
 +
 +    v8::HandleScope handle_scope;
 +    v8::Context::Scope scope(workerEngine->context());
 +
 +    v8::Handle<v8::Value> value = QV8Worker::deserialize(data, workerEngine);
 +
 +    v8::TryCatch tc;
 +    workerEngine->callOnMessage(script->object, value);
 +
 +    if (tc.HasCaught()) {
 +        QQmlError error;
 +        QQmlExpressionPrivate::exceptionToError(tc.Message(), error);
 +        reportScriptException(script, error);
 +    }
 +}
 +
 +void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
 +{
 +    if (url.isRelative())
 +        return;
 +
 +    QString fileName = QQmlEnginePrivate::urlToLocalFileOrQrc(url);
 +
 +    QFile f(fileName);
 +    if (f.open(QIODevice::ReadOnly)) {
 +        QByteArray data = f.readAll();
 +        QString sourceCode = QString::fromUtf8(data);
 +        QQmlScript::Parser::extractPragmas(sourceCode);
 +
 +        v8::HandleScope handle_scope;
 +        v8::Context::Scope scope(workerEngine->context());
 +
 +        WorkerScript *script = workers.value(id);
 +        if (!script)
 +            return;
 +        script->source = url;
 +        v8::Handle<v8::Object> activation = getWorker(script);
 +        if (activation.IsEmpty())
 +            return;
 +
 +        // XXX ???
 +        // workerEngine->baseUrl = url;
 +
 +        v8::TryCatch tc;
 +        v8::Local<v8::Script> program = workerEngine->qmlModeCompile(sourceCode, url.toString());
 +
 +        if (!tc.HasCaught()) 
 +            program->Run(activation);
 +        
 +        if (tc.HasCaught()) {
 +            QQmlError error;
 +            QQmlExpressionPrivate::exceptionToError(tc.Message(), error);
 +            reportScriptException(script, error);
 +        }
 +    } else {
 +        qWarning().nospace() << "WorkerScript: Cannot find source file " << url.toString();
 +    }
 +}
 +
 +void QQuickWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script, 
 +                                                                  const QQmlError &error)
 +{
 +    QQuickWorkerScriptEnginePrivate *p = QQuickWorkerScriptEnginePrivate::get(workerEngine);
 +
 +    QMutexLocker(&p->m_lock);
 +    if (script->owner)
 +        QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error));
 +}
 +
 +WorkerDataEvent::WorkerDataEvent(int workerId, const QByteArray &data)
 +: QEvent((QEvent::Type)WorkerData), m_id(workerId), m_data(data)
 +{
 +}
 +
 +WorkerDataEvent::~WorkerDataEvent()
 +{
 +}
 +
 +int WorkerDataEvent::workerId() const
 +{
 +    return m_id;
 +}
 +
 +QByteArray WorkerDataEvent::data() const
 +{
 +    return m_data;
 +}
 +
 +WorkerLoadEvent::WorkerLoadEvent(int workerId, const QUrl &url)
 +: QEvent((QEvent::Type)WorkerLoad), m_id(workerId), m_url(url)
 +{
 +}
 +
 +int WorkerLoadEvent::workerId() const
 +{
 +    return m_id;
 +}
 +
 +QUrl WorkerLoadEvent::url() const
 +{
 +    return m_url;
 +}
 +
 +WorkerRemoveEvent::WorkerRemoveEvent(int workerId)
 +: QEvent((QEvent::Type)WorkerRemove), m_id(workerId)
 +{
 +}
 +
 +int WorkerRemoveEvent::workerId() const
 +{
 +    return m_id;
 +}
 +
 +WorkerErrorEvent::WorkerErrorEvent(const QQmlError &error)
 +: QEvent((QEvent::Type)WorkerError), m_error(error)
 +{
 +}
 +
 +QQmlError WorkerErrorEvent::error() const
 +{
 +    return m_error;
 +}
 +
 +QQuickWorkerScriptEngine::QQuickWorkerScriptEngine(QQmlEngine *parent)
 +: QThread(parent), d(new QQuickWorkerScriptEnginePrivate(parent))
 +{
 +    d->m_lock.lock();
 +    connect(d, SIGNAL(stopThread()), this, SLOT(quit()), Qt::DirectConnection);
 +    start(QThread::LowestPriority);
 +    d->m_wait.wait(&d->m_lock);
 +    d->moveToThread(this);
 +    d->m_lock.unlock();
 +}
 +
 +QQuickWorkerScriptEngine::~QQuickWorkerScriptEngine()
 +{
 +    d->m_lock.lock();
 +    QCoreApplication::postEvent(d, new QEvent((QEvent::Type)QQuickWorkerScriptEnginePrivate::WorkerDestroyEvent));
 +    d->m_lock.unlock();
 +
 +    //We have to force to cleanup the main thread's event queue here
 +    //to make sure the main GUI release all pending locks/wait conditions which
 +    //some worker script/agent are waiting for (QQuickListModelWorkerAgent::sync() for example).
 +    QCoreApplication::processEvents();
 +    wait();
 +    d->deleteLater();
 +}
 +
 +QQuickWorkerScriptEnginePrivate::WorkerScript::WorkerScript()
 +: id(-1), initialized(false), owner(0)
 +{
 +}
 +
 +QQuickWorkerScriptEnginePrivate::WorkerScript::~WorkerScript()
 +{
 +    qPersistentDispose(object);
 +}
 +
 +int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner)
 +{
 +    typedef QQuickWorkerScriptEnginePrivate::WorkerScript WorkerScript;
 +    WorkerScript *script = new WorkerScript;
 +
 +    script->id = d->m_nextId++;
 +    script->owner = owner;
 +
 +    d->m_lock.lock();
 +    d->workers.insert(script->id, script);
 +    d->m_lock.unlock();
 +
 +    return script->id;
 +}
 +
 +void QQuickWorkerScriptEngine::removeWorkerScript(int id)
 +{
 +    QQuickWorkerScriptEnginePrivate::WorkerScript* script = d->workers.value(id);
 +    if (script) {
 +        script->owner = 0;
 +        QCoreApplication::postEvent(d, new WorkerRemoveEvent(id));
 +    }
 +}
 +
 +void QQuickWorkerScriptEngine::executeUrl(int id, const QUrl &url)
 +{
 +    QCoreApplication::postEvent(d, new WorkerLoadEvent(id, url));
 +}
 +
 +void QQuickWorkerScriptEngine::sendMessage(int id, const QByteArray &data)
 +{
 +    QCoreApplication::postEvent(d, new WorkerDataEvent(id, data));
 +}
 +
 +void QQuickWorkerScriptEngine::run()
 +{
 +    d->m_lock.lock();
 +
 +    d->workerEngine = new QQuickWorkerScriptEnginePrivate::WorkerEngine(d);
 +    d->workerEngine->init();
 +
 +    d->m_wait.wakeAll();
 +
 +    d->m_lock.unlock();
 +
 +    exec();
 +
 +    qDeleteAll(d->workers);
 +    d->workers.clear();
 +
 +    delete d->workerEngine; d->workerEngine = 0;
 +}
 +
 +
 +/*!
 +    \qmlclass WorkerScript QQuickWorkerScript
 +    \ingroup qml-utility-elements
 +    \brief The WorkerScript element enables the use of threads in QML.
 +
 +    Use WorkerScript to run operations in a new thread.
 +    This is useful for running operations in the background so
 +    that the main GUI thread is not blocked.
 +
 +    Messages can be passed between the new thread and the parent thread
 +    using \l sendMessage() and the \l {WorkerScript::onMessage}{onMessage()} handler.
 +
 +    An example:
 +
 +    \snippet doc/src/snippets/qml/workerscript.qml 0
 +
 +    The above worker script specifies a JavaScript file, "script.js", that handles
 +    the operations to be performed in the new thread. Here is \c script.js:
 +
 +    \quotefile doc/src/snippets/qml/script.js
 +
 +    When the user clicks anywhere within the rectangle, \c sendMessage() is
 +    called, triggering the \tt WorkerScript.onMessage() handler in
 +    \tt script.js. This in turn sends a reply message that is then received
 +    by the \tt onMessage() handler of \tt myWorker.
 +
 +
 +    \section3 Restrictions
 +
 +    Since the \c WorkerScript.onMessage() function is run in a separate thread, the
 +    JavaScript file is evaluated in a context separate from the main QML engine. This means
 +    that unlike an ordinary JavaScript file that is imported into QML, the \c script.js
 +    in the above example cannot access the properties, methods or other attributes
 +    of the QML item, nor can it access any context properties set on the QML object
 +    through QQmlContext.
 +
 +    Additionally, there are restrictions on the types of values that can be passed to and
 +    from the worker script. See the sendMessage() documentation for details.
 +
 +    \sa {declarative/threading/workerscript}{WorkerScript example},
 +        {declarative/threading/threadedlistmodel}{Threaded ListModel example}
 +*/
 +QQuickWorkerScript::QQuickWorkerScript(QObject *parent)
 +: QObject(parent), m_engine(0), m_scriptId(-1), m_componentComplete(true)
 +{
 +}
 +
 +QQuickWorkerScript::~QQuickWorkerScript()
 +{
 +    if (m_scriptId != -1) m_engine->removeWorkerScript(m_scriptId);
 +}
 +
 +/*!
 +    \qmlproperty url WorkerScript::source
 +
 +    This holds the url of the JavaScript file that implements the
 +    \tt WorkerScript.onMessage() handler for threaded operations.
 +*/
 +QUrl QQuickWorkerScript::source() const
 +{
 +    return m_source;
 +}
 +
 +void QQuickWorkerScript::setSource(const QUrl &source)
 +{
 +    if (m_source == source)
 +        return;
 +
 +    m_source = source;
 +
 +    if (engine())
 +        m_engine->executeUrl(m_scriptId, m_source);
 +
 +    emit sourceChanged();
 +}
 +
 +/*!
 +    \qmlmethod WorkerScript::sendMessage(jsobject message)
 +
 +    Sends the given \a message to a worker script handler in another
 +    thread. The other worker script handler can receive this message
 +    through the onMessage() handler.
 +
 +    The \c message object may only contain values of the following
 +    types:
 +
 +    \list
 +    \o boolean, number, string
 +    \o JavaScript objects and arrays
 +    \o ListModel objects (any other type of QObject* is not allowed)
 +    \endlist
 +
 +    All objects and arrays are copied to the \c message. With the exception
 +    of ListModel objects, any modifications by the other thread to an object
 +    passed in \c message will not be reflected in the original object.
 +*/
 +void QQuickWorkerScript::sendMessage(QQmlV8Function *args)
 +{
 +    if (!engine()) {
 +        qWarning("QQuickWorkerScript: Attempt to send message before WorkerScript establishment");
 +        return;
 +    }
 +
 +    v8::Handle<v8::Value> argument = v8::Undefined();
 +    if (args->Length() != 0) 
 +        argument = (*args)[0];
 +
 +    m_engine->sendMessage(m_scriptId, QV8Worker::serialize(argument, args->engine()));
 +}
 +
 +void QQuickWorkerScript::classBegin()
 +{
 +    m_componentComplete = false;
 +}
 +
 +QQuickWorkerScriptEngine *QQuickWorkerScript::engine()
 +{
 +    if (m_engine) return m_engine;
 +    if (m_componentComplete) {
 +        QQmlEngine *engine = qmlEngine(this);
 +        if (!engine) {
 +            qWarning("QQuickWorkerScript: engine() called without qmlEngine() set");
 +            return 0;
 +        }
 +
 +        m_engine = QQmlEnginePrivate::get(engine)->getWorkerScriptEngine();
 +        m_scriptId = m_engine->registerWorkerScript(this);
 +
 +        if (m_source.isValid())
 +            m_engine->executeUrl(m_scriptId, m_source);
 +
 +        return m_engine;
 +    }
 +    return 0;
 +}
 +
 +void QQuickWorkerScript::componentComplete()
 +{
 +    m_componentComplete = true;
 +    engine(); // Get it started now.
 +}
 +
 +/*!
 +    \qmlsignal WorkerScript::onMessage(jsobject msg)
 +
 +    This handler is called when a message \a msg is received from a worker
 +    script in another thread through a call to sendMessage().
 +*/
 +
 +bool QQuickWorkerScript::event(QEvent *event)
 +{
 +    if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
 +        QQmlEngine *engine = qmlEngine(this);
 +        if (engine) {
 +            WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
 +            QV8Engine *v8engine = QQmlEnginePrivate::get(engine)->v8engine();
 +            v8::HandleScope handle_scope;
 +            v8::Context::Scope scope(v8engine->context());
 +            v8::Handle<v8::Value> value = QV8Worker::deserialize(workerEvent->data(), v8engine);
 +            emit message(QQmlV8Handle::fromHandle(value));
 +        }
 +        return true;
 +    } else if (event->type() == (QEvent::Type)WorkerErrorEvent::WorkerError) {
 +        WorkerErrorEvent *workerEvent = static_cast<WorkerErrorEvent *>(event);
 +        QQmlEnginePrivate::warning(qmlEngine(this), workerEvent->error());
 +        return true;
 +    } else {
 +        return QObject::event(event);
 +    }
 +}
 +
 +QT_END_NAMESPACE
 +
 +#include <qquickworkerscript.moc>
 +
index c03292d,0000000..4fd8494
mode 100644,000000..100644
--- /dev/null
@@@ -1,1538 -1,0 +1,1615 @@@
-     return property;
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +// #define REGISTER_CLEANUP_DEBUG
 +
 +#include "qv4bindings_p.h"
 +#include "qv4program_p.h"
 +#include "qv4compiler_p.h"
 +#include "qv4compiler_p_p.h"
 +
 +#include <private/qqmlaccessors_p.h>
 +#include <private/qqmlprofilerservice_p.h>
 +#include <private/qqmlmetatype_p.h>
 +#include <private/qqmltrace_p.h>
++#include <private/qqmlstringconverters_p.h>
 +
 +#include <QtQml/qqmlinfo.h>
 +#include <QtCore/qnumeric.h>
 +#include <QtCore/qmath.h>
 +#include <math.h> // ::fmod
 +
 +QT_BEGIN_NAMESPACE
 +
 +using namespace QQmlJS;
 +
 +namespace {
 +struct Register {
 +    typedef QQmlRegisterType Type;
 +
 +    void setUndefined() { dataType = UndefinedType; }
 +    void setNaN() { setqreal(qSNaN()); }
 +    bool isUndefined() const { return dataType == UndefinedType; }
 +
 +    void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; }
 +    QObject *getQObject() const { return qobjectValue; }
 +
 +    void setqreal(qreal v) { qrealValue = v; dataType = QRealType; }
 +    qreal getqreal() const { return qrealValue; }
 +    qreal &getqrealref() { return qrealValue; }
 +
 +    void setint(int v) { intValue = v; dataType = IntType; }
 +    int getint() const { return intValue; }
 +    int &getintref() { return intValue; }
 +
 +    void setbool(bool v) { boolValue = v; dataType = BoolType; }
 +    bool getbool() const { return boolValue; }
 +    bool &getboolref() { return boolValue; }
 +
 +    QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
 +    QString *getstringptr() { return (QString *)typeDataPtr(); }
 +    QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
++    QColor *getcolorptr() { return (QColor *)typeDataPtr(); }
 +    const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
 +    const QString *getstringptr() const { return (QString *)typeDataPtr(); }
 +    const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
++    const QColor *getcolorptr() const { return (QColor *)typeDataPtr(); }
 +
 +    void *typeDataPtr() { return (void *)&data; }
 +    void *typeMemory() { return (void *)data; }
 +    const void *typeDataPtr() const { return (void *)&data; }
 +    const void *typeMemory() const { return (void *)data; }
 +
 +    Type gettype() const { return dataType; }
 +    void settype(Type t) { dataType = t; }
 +
 +    Type dataType;     // Type of data
 +    union {
 +        QObject *qobjectValue;
 +        qreal qrealValue;
 +        int intValue;
 +        bool boolValue;
 +        void *data[sizeof(QVariant)];
 +        qint64 q_for_alignment_1;
 +        double q_for_alignment_2;
 +    };
 +
 +    inline void cleanup();
 +    inline void cleanupString();
 +    inline void cleanupUrl();
++    inline void cleanupColor();
 +    inline void cleanupVariant();
 +
 +    inline void copy(const Register &other);
 +    inline void init(Type type);
 +#ifdef REGISTER_CLEANUP_DEBUG
 +    Register() {
 +        type = 0;
 +    }
 +
 +    ~Register() {
 +        if (dataType >= FirstCleanupType)
 +            qWarning("Register leaked of type %d", dataType);
 +    }
 +#endif
 +};
 +
 +void Register::cleanup()
 +{
 +    if (dataType >= FirstCleanupType) {
 +        if (dataType == QStringType) {
 +            getstringptr()->~QString();
 +        } else if (dataType == QUrlType) {
 +            geturlptr()->~QUrl();
++        } else if (dataType == QColorType) {
++            getcolorptr()->~QColor();
 +        } else if (dataType == QVariantType) {
 +            getvariantptr()->~QVariant();
 +        }
 +    }
 +    setUndefined();
 +}
 +
 +void Register::cleanupString()
 +{
 +    getstringptr()->~QString();
 +    setUndefined();
 +}
 +
 +void Register::cleanupUrl()
 +{
 +    geturlptr()->~QUrl();
 +    setUndefined();
 +}
 +
++void Register::cleanupColor()
++{
++    getcolorptr()->~QColor();
++    setUndefined();
++}
++
 +void Register::cleanupVariant()
 +{
 +    getvariantptr()->~QVariant();
 +    setUndefined();
 +}
 +
 +void Register::copy(const Register &other)
 +{
 +    *this = other;
 +    if (other.dataType >= FirstCleanupType) {
 +        if (other.dataType == QStringType) 
 +            new (getstringptr()) QString(*other.getstringptr());
 +        else if (other.dataType == QUrlType)
 +            new (geturlptr()) QUrl(*other.geturlptr());
++        else if (other.dataType == QColorType)
++            new (getcolorptr()) QColor(*other.getcolorptr());
 +        else if (other.dataType == QVariantType)
 +            new (getvariantptr()) QVariant(*other.getvariantptr());
 +    } 
 +}
 +
 +void Register::init(Type type)
 +{
 +    dataType = type;
 +    if (dataType >= FirstCleanupType) {
 +        if (dataType == QStringType) 
 +            new (getstringptr()) QString();
 +        else if (dataType == QUrlType)
 +            new (geturlptr()) QUrl();
++        else if (dataType == QColorType)
++            new (getcolorptr()) QColor();
 +        else if (dataType == QVariantType)
 +            new (getvariantptr()) QVariant();
 +    }
 +}
 +
 +} // end of anonymous namespace
 +
 +QV4Bindings::QV4Bindings(const char *programData, 
 +                                               QQmlContextData *context, 
 +                                               QQmlRefCount *ref)
 +: subscriptions(0), program(0), dataRef(0), bindings(0)
 +{
 +    program = (QV4Program *)programData;
 +    dataRef = ref;
 +    if (dataRef) dataRef->addref();
 +
 +    if (program) {
 +        subscriptions = new Subscription[program->subscriptions];
 +        bindings = new Binding[program->bindings];
 +
 +        QQmlAbstractExpression::setContext(context);
 +    }
 +}
 +
 +QV4Bindings::~QV4Bindings()
 +{
 +    delete [] bindings;
 +    delete [] subscriptions; subscriptions = 0;
 +    if (dataRef) dataRef->release();
 +}
 +
 +QQmlAbstractBinding *QV4Bindings::configBinding(int index, QObject *target, 
 +                                                        QObject *scope, int property,
 +                                                        int line, int column)
 +{
 +    Binding *rv = bindings + index;
 +
 +    rv->index = index;
 +    rv->property = property;
 +    rv->target = target;
 +    rv->scope = scope;
 +    rv->line = line;
 +    rv->column = column;
 +    rv->parent = this;
 +
 +    addref(); // This is decremented in Binding::destroy()
 +
 +    return rv;
 +}
 +
 +void QV4Bindings::Binding::setEnabled(bool e, QQmlPropertyPrivate::WriteFlags flags)
 +{
 +    if (enabled != e) {
 +        enabled = e;
 +
 +        if (e) update(flags);
 +    }
 +}
 +
 +void QV4Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags)
 +{
 +    parent->run(this, flags);
 +}
 +
 +void QV4Bindings::Binding::destroy()
 +{
 +    enabled = false;
 +    removeFromObject();
 +    clear();
 +    removeError();
 +    parent->release();
 +}
 +
 +int QV4Bindings::Binding::propertyIndex() const
 +{
++    //mask out the type information set for value types
++    return property & 0xFF00FFFF;
 +}
 +
 +QObject *QV4Bindings::Binding::object() const
 +{
 +    return target;
 +}
 +
 +void QV4Bindings::Subscription::subscriptionCallback(QQmlNotifierEndpoint *e) 
 +{
 +    Subscription *s = static_cast<Subscription *>(e);
 +    s->bindings->subscriptionNotify(s->method);
 +}
 +
 +void QV4Bindings::subscriptionNotify(int id)
 +{
 +    QV4Program::BindingReferenceList *list = program->signalTable(id);
 +
 +    for (quint32 ii = 0; ii < list->count; ++ii) {
 +        QV4Program::BindingReference *bindingRef = list->bindings + ii;
 +
 +        Binding *binding = bindings + bindingRef->binding;
 +
 +        if (binding->executedBlocks & bindingRef->blockMask) {
 +            run(binding, QQmlPropertyPrivate::DontRemoveBinding);
 +        }
 +    }
 +}
 +
 +void QV4Bindings::run(Binding *binding, QQmlPropertyPrivate::WriteFlags flags)
 +{
 +    if (!binding->enabled)
 +        return;
 +
 +    QQmlContextData *context = QQmlAbstractExpression::context();
 +    if (!context || !context->isValid()) 
 +        return;
 +
 +    QQmlTrace trace("V4 Binding Update");
 +    trace.addDetail("URL", context->url);
 +    trace.addDetail("Line", binding->line);
 +    trace.addDetail("Column", binding->column);
 +
 +    QQmlBindingProfiler prof(context->urlString, binding->line, binding->column);
 +
 +    if (binding->updating) {
 +        QString name;
 +        if (binding->property & 0xFFFF0000) {
 +            QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
 +
 +            QQmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
 +            Q_ASSERT(vt);
 +
 +            name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name());
 +            name.append(QLatin1String("."));
 +            name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name()));
 +        } else {
 +            name = QLatin1String(binding->target->metaObject()->property(binding->property).name());
 +        }
 +        qmlInfo(binding->target) << tr("Binding loop detected for property \"%1\"").arg(name);
 +        return;
 +    }
 +
 +    binding->updating = true;
 +    if (binding->property & 0xFFFF0000) {
 +        QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
 +
 +        QQmlValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
 +        Q_ASSERT(vt);
 +        vt->read(binding->target, binding->property & 0xFFFF);
 +
 +        QObject *target = vt;
 +        run(binding->index, binding->executedBlocks, context, binding, binding->scope, target, flags);
 +
 +        vt->write(binding->target, binding->property & 0xFFFF, flags);
 +    } else {
 +        run(binding->index, binding->executedBlocks, context, binding, binding->scope, binding->target, flags);
 +    }
 +    binding->updating = false;
 +}
 +
 +
 +void QV4Bindings::unsubscribe(int subIndex)
 +{
 +    Subscription *sub = (subscriptions + subIndex);
 +    sub->disconnect();
 +}
 +
 +void QV4Bindings::subscribeId(QQmlContextData *p, int idIndex, int subIndex)
 +{
 +    unsubscribe(subIndex);
 +
 +    if (p->idValues[idIndex]) {
 +        Subscription *sub = (subscriptions + subIndex);
 +        sub->bindings = this;
 +        sub->method = subIndex;
 +        sub->connect(&p->idValues[idIndex].bindings);
 +    }
 +}
 + 
 +void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex)
 +{
 +    Subscription *sub = (subscriptions + subIndex);
 +    if (sub->isConnected(o, notifyIndex))
 +        return;
 +    sub->bindings = this;
 +    sub->method = subIndex; 
 +    if (o)
 +        sub->connect(o, notifyIndex);
 +    else
 +        sub->disconnect();
 +}
 +
 +// Conversion functions - these MUST match the QtScript expression path
 +inline static qreal toReal(Register *reg, int type, bool *ok = 0)
 +{
 +    if (ok) *ok = true;
 +
 +    if (type == QMetaType::QReal) {
 +        return reg->getqreal();
 +    } else if (type == qMetaTypeId<QVariant>()) {
 +        return reg->getvariantptr()->toReal();
 +    } else {
 +        if (ok) *ok = false;
 +        return 0;
 +    }
 +}
 +
 +inline static QString toString(Register *reg, int type, bool *ok = 0)
 +{
 +    if (ok) *ok = true;
 +
 +    if (type == QMetaType::QReal) {
 +        return QString::number(reg->getqreal());
 +    } else if (type == QMetaType::Int) {
 +        return QString::number(reg->getint());
 +    } else if (type == qMetaTypeId<QVariant>()) {
 +        return reg->getvariantptr()->toString();
 +    } else if (type == QMetaType::QString) {
 +        return *reg->getstringptr();
 +    } else {
 +        if (ok) *ok = false;
 +        return QString();
 +    }
 +}
 +
 +inline static bool toBool(Register *reg, int type, bool *ok = 0)
 +{
 +    if (ok) *ok = true;
 +
 +    if (type == QMetaType::Bool) {
 +        return reg->getbool();
 +    } else if (type == qMetaTypeId<QVariant>()) {
 +        return reg->getvariantptr()->toBool();
 +    } else {
 +        if (ok) *ok = false;
 +        return false;
 +    }
 +}
 +
 +inline static QUrl toUrl(Register *reg, int type, QQmlContextData *context, bool *ok = 0)
 +{
 +    if (ok) *ok = true;
 +
 +    QUrl base;
 +    if (type == qMetaTypeId<QVariant>()) {
 +        QVariant *var = reg->getvariantptr();
 +        int vt = var->type();
 +        if (vt == QVariant::Url) {
 +            base = var->toUrl();
 +        } else if (vt == QVariant::ByteArray) {
 +            // Preserve any valid percent-encoded octets supplied by the source
 +            base.setEncodedUrl(var->toByteArray(), QUrl::TolerantMode);
 +        } else if (vt == QVariant::String) {
 +            base.setEncodedUrl(var->toString().toUtf8(), QUrl::TolerantMode);
 +        } else {
 +            if (ok) *ok = false;
 +            return QUrl();
 +        }
 +    } else if (type == QMetaType::QString) {
 +        base.setEncodedUrl(reg->getstringptr()->toUtf8(), QUrl::TolerantMode);
 +    } else {
 +        if (ok) *ok = false;
 +        return QUrl();
 +    }
 +
 +    if (!base.isEmpty() && base.isRelative())
 +        return context->url.resolved(base);
 +    else
 +        return base;
 +}
 +
 +static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4)
 +{
 +    QVariant qtscript = qtscriptRaw;
 +
 +    if (qtscript.userType() == v4.userType()) {
 +    } else if (qtscript.canConvert((QVariant::Type)v4.userType())) {
 +        qtscript.convert((QVariant::Type)v4.userType());
 +    } else if (qtscript.userType() == QVariant::Invalid && v4.userType() == QMetaType::QObjectStar) {
 +        qtscript = qVariantFromValue<QObject *>(0);
 +    } else {
 +        return false;
 +    }
 +
 +    int type = qtscript.userType();
 +
 +    if (type == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
 +        return QQmlMetaType::QQuickAnchorLineCompare(qtscript.constData(), v4.constData());
 +    } else if (type == QMetaType::Double) {
 +
 +        double la = qvariant_cast<double>(qtscript);
 +        double lr = qvariant_cast<double>(v4);
 +
 +        return la == lr || (qIsNaN(la) && qIsNaN(lr));
 +
 +    } else if (type == QMetaType::Float) {
 +
 +        float la = qvariant_cast<float>(qtscript);
 +        float lr = qvariant_cast<float>(v4);
 +
 +        return la == lr || (qIsNaN(la) && qIsNaN(lr));
 +
 +    } else {
 +        return qtscript == v4;
 +    }
 +}
 +
 +QByteArray testResultToString(const QVariant &result, bool undefined)
 +{
 +    if (undefined) {
 +        return "undefined";
 +    } else {
 +        QString rv;
 +        QDebug d(&rv);
 +        d << result;
 +        return rv.toUtf8();
 +    }
 +}
 +
 +static void testBindingResult(const QString &binding, int line, int column, 
 +                              QQmlContextData *context, QObject *scope, 
 +                              const Register &result, int resultType)
 +{
 +    QQmlExpression expression(context->asQQmlContext(), scope, binding);
 +    bool isUndefined = false;
 +    QVariant value = expression.evaluate(&isUndefined);
 +
 +    bool iserror = false;
 +    QByteArray qtscriptResult;
 +    QByteArray v4Result;
 +
 +    if (expression.hasError()) {
 +        iserror = true;
 +        qtscriptResult = "exception";
 +    } else {
 +        qtscriptResult = testResultToString(value, isUndefined);
 +    }
 +
 +    if (isUndefined && result.isUndefined()) {
 +        return;
 +    } else if(isUndefined != result.isUndefined()) {
 +        iserror = true;
 +    } 
 +    
 +    QVariant v4value;
 +    if (!result.isUndefined()) {
 +        switch (resultType) {
 +        case QMetaType::QString:
 +            v4value = *result.getstringptr();
 +            break;
 +        case QMetaType::QUrl:
 +            v4value = *result.geturlptr();
 +            break;
 +        case QMetaType::QObjectStar:
 +            v4value = qVariantFromValue<QObject *>(result.getQObject());
 +            break;
 +        case QMetaType::Bool:
 +            v4value = result.getbool();
 +            break;
 +        case QMetaType::Int:
 +            v4value = result.getint();
 +            break;
 +        case QMetaType::QReal:
 +            v4value = result.getqreal();
 +            break;
 +        default:
 +            if (resultType == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
 +                v4value = QVariant(QQmlMetaType::QQuickAnchorLineMetaTypeId(), result.typeDataPtr());
 +            } else {
 +                iserror = true;
 +                v4Result = "Unknown V4 type";
 +            }
 +        }
 +    }
 +    if (v4Result.isEmpty())
 +        v4Result = testResultToString(v4value, result.isUndefined());
 +
 +    if (!testCompareVariants(value, v4value)) 
 +        iserror = true;
 +
 +    if (iserror) {
 +        qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column;
 +
 +        qWarning().nospace() << "    Binding:  " << binding;
 +        qWarning().nospace() << "    QtScript: " << qtscriptResult.constData();
 +        qWarning().nospace() << "    V4:       " << v4Result.constData();
 +    }
 +}
 +
 +static void testBindingException(const QString &binding, int line, int column, 
 +                                 QQmlContextData *context, QObject *scope)
 +{
 +    QQmlExpression expression(context->asQQmlContext(), scope, binding);
 +    bool isUndefined = false;
 +    QVariant value = expression.evaluate(&isUndefined);
 +
 +    if (!expression.hasError()) {
 +        QByteArray qtscriptResult = testResultToString(value, isUndefined);
 +        qWarning().nospace() << "QV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column;
 +        qWarning().nospace() << "    Binding:  " << binding;
 +        qWarning().nospace() << "    QtScript: " << qtscriptResult.constData();
 +        qWarning().nospace() << "    V4:       exception";
 +    }
 +}
 +
 +static void throwException(int id, QQmlDelayedError *error, 
 +                           QV4Program *program, QQmlContextData *context,
 +                           const QString &description = QString())
 +{
 +    error->error.setUrl(context->url);
 +    if (description.isEmpty())
 +        error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object"));
 +    else
 +        error->error.setDescription(description);
 +    if (id != 0xFF) {
 +        quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id); 
 +        error->error.setLine((e >> 32) & 0xFFFFFFFF);
 +        error->error.setColumn(e & 0xFFFFFFFF); 
 +    } else {
 +        error->error.setLine(-1);
 +        error->error.setColumn(-1);
 +    }
 +    if (!context->engine || !error->addError(QQmlEnginePrivate::get(context->engine)))
 +        QQmlEnginePrivate::warning(context->engine, error->error);
 +}
 +
 +const qreal QV4Bindings::D32 = 4294967296.0;
 +
 +qint32 QV4Bindings::toInt32(qreal n)
 +{
 +    if (qIsNaN(n) || qIsInf(n) || (n == 0))
 +        return 0;
 +
 +    double sign = (n < 0) ? -1.0 : 1.0;
 +    qreal abs_n = fabs(n);
 +
 +    n = ::fmod(sign * ::floor(abs_n), D32);
 +    const double D31 = D32 / 2.0;
 +
 +    if (sign == -1 && n < -D31)
 +        n += D32;
 +
 +    else if (sign != -1 && n >= D31)
 +        n -= D32;
 +
 +    return qint32 (n);
 +}
 +
 +inline quint32 QV4Bindings::toUint32(qreal n)
 +{
 +    if (qIsNaN(n) || qIsInf(n) || (n == 0))
 +        return 0;
 +
 +    double sign = (n < 0) ? -1.0 : 1.0;
 +    qreal abs_n = fabs(n);
 +
 +    n = ::fmod(sign * ::floor(abs_n), D32);
 +
 +    if (n < 0)
 +        n += D32;
 +
 +    return quint32 (n);
 +}
 +
 +#define THROW_EXCEPTION_STR(id, str) { \
 +    if (testBinding) testBindingException(*testBindingSource, bindingLine, bindingColumn, context, scope); \
 +    throwException((id), error, program, context, (str)); \
 +    goto exceptionExit; \
 +} 
 +
 +#define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString())
 +
 +#define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg))
 +#define MARK_CLEAN_REGISTER(reg) cleanupRegisterMask &= ~(1 << (reg))
 +
 +#define STRING_REGISTER(reg) { \
 +    registers[(reg)].settype(QStringType); \
 +    MARK_REGISTER(reg); \
 +}
 +
 +#define URL_REGISTER(reg) { \
 +    registers[(reg)].settype(QUrlType); \
 +    MARK_REGISTER(reg); \
 +}
 +
++#define COLOR_REGISTER(reg) { \
++    registers[(reg)].settype(QColorType); \
++    MARK_REGISTER(reg); \
++}
++
 +#define VARIANT_REGISTER(reg) { \
 +    registers[(reg)].settype(QVariantType); \
 +    MARK_REGISTER(reg); \
 +}
 +
 +#ifdef QML_THREADED_INTERPRETER
 +void **QV4Bindings::getDecodeInstrTable()
 +{
 +    static void **decode_instr;
 +    if (!decode_instr) {
 +        QV4Bindings *dummy = new QV4Bindings(0, 0, 0);
 +        quint32 executedBlocks = 0;
 +        dummy->run(0, executedBlocks, 0, 0, 0, 0, 
 +                   QQmlPropertyPrivate::BypassInterceptor, 
 +                   &decode_instr);
 +        dummy->release();
 +    }
 +    return decode_instr;
 +}
 +#endif
 +
 +void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
 +                                 QQmlContextData *context, QQmlDelayedError *error,
 +                                 QObject *scope, QObject *output, 
 +                                 QQmlPropertyPrivate::WriteFlags storeFlags
 +#ifdef QML_THREADED_INTERPRETER
 +                                 ,void ***table
 +#endif
 +                                 )
 +{
 +#ifdef QML_THREADED_INTERPRETER
 +    if (table) {
 +        static void *decode_instr[] = {
 +            FOR_EACH_V4_INSTR(QML_V4_INSTR_ADDR)
 +        };
 +
 +        *table = decode_instr;
 +        return;
 +    }
 +#endif
 +
 +
 +    error->removeError();
 +
 +    Register registers[32];
 +    quint32 cleanupRegisterMask = 0;
 +
 +    executedBlocks = 0;
 +
 +    const char *code = program->instructions();
 +    code += instrIndex * QML_V4_INSTR_SIZE(Jump, jump);
 +    const V4Instr *instr = reinterpret_cast<const V4Instr *>(code);
 +
 +    const char *data = program->data();
 +
 +    QString *testBindingSource = 0;
 +    bool testBinding = false;
 +    int bindingLine = 0;
 +    int bindingColumn = 0;
 +
 +#ifdef QML_THREADED_INTERPRETER
 +    goto *instr->common.code;
 +#else
 +    for (;;) {
 +        switch (instr->common.type) {
 +#endif
 +
 +    QML_V4_BEGIN_INSTR(Noop, common)
 +    QML_V4_END_INSTR(Noop, common)
 +
 +    QML_V4_BEGIN_INSTR(BindingId, id)
 +        bindingLine = instr->id.line;
 +        bindingColumn = instr->id.column;
 +    QML_V4_END_INSTR(BindingId, id)
 +
 +    QML_V4_BEGIN_INSTR(SubscribeId, subscribeop)
 +        subscribeId(context, instr->subscribeop.index, instr->subscribeop.offset);
 +    QML_V4_END_INSTR(SubscribeId, subscribeop)
 +
 +    QML_V4_BEGIN_INSTR(Subscribe, subscribeop)
 +    {
 +        QObject *o = 0;
 +        const Register &object = registers[instr->subscribeop.reg];
 +        if (!object.isUndefined()) o = object.getQObject();
 +        subscribe(o, instr->subscribeop.index, instr->subscribeop.offset);
 +    }
 +    QML_V4_END_INSTR(Subscribe, subscribeop)
 +
 +    QML_V4_BEGIN_INSTR(FetchAndSubscribe, fetchAndSubscribe)
 +    {
 +        Register &reg = registers[instr->fetchAndSubscribe.reg];
 +
 +        if (reg.isUndefined()) 
 +            THROW_EXCEPTION(instr->fetchAndSubscribe.exceptionId);
 +
 +        QObject *object = reg.getQObject();
 +        if (!object) {
 +            reg.setUndefined();
 +        } else {
 +            int subIdx = instr->fetchAndSubscribe.subscription;
 +            Subscription *sub = 0;
 +            if (subIdx != -1) {
 +                sub = (subscriptions + subIdx);
 +                sub->bindings = this;
 +                sub->method = subIdx;
 +            }
 +            reg.init((Register::Type)instr->fetchAndSubscribe.valueType);
 +            if (instr->fetchAndSubscribe.valueType >= FirstCleanupType)
 +                MARK_REGISTER(instr->fetchAndSubscribe.reg);
 +            QQmlAccessors *accessors = instr->fetchAndSubscribe.property.accessors;
 +            accessors->read(object, instr->fetchAndSubscribe.property.accessorData,
 +                            reg.typeDataPtr());
 +
 +            if (accessors->notifier) {
 +                QQmlNotifier *notifier = 0;
 +                accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, &notifier);
 +                if (notifier) sub->connect(notifier);
 +            } else if (instr->fetchAndSubscribe.property.notifyIndex != -1) {
 +                sub->connect(object, instr->fetchAndSubscribe.property.notifyIndex);
 +            }
 +        }
 +    }
 +    QML_V4_END_INSTR(FetchAndSubscribe, fetchAndSubscribe)
 +
 +    QML_V4_BEGIN_INSTR(LoadId, load)
 +        registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data());
 +    QML_V4_END_INSTR(LoadId, load)
 +
 +    QML_V4_BEGIN_INSTR(LoadScope, load)
 +        registers[instr->load.reg].setQObject(scope);
 +    QML_V4_END_INSTR(LoadScope, load)
 +
 +    QML_V4_BEGIN_INSTR(LoadRoot, load)
 +        registers[instr->load.reg].setQObject(context->contextObject);
 +    QML_V4_END_INSTR(LoadRoot, load)
 +
 +    QML_V4_BEGIN_INSTR(LoadAttached, attached)
 +    {
 +        const Register &input = registers[instr->attached.reg];
 +        Register &output = registers[instr->attached.output];
 +        if (input.isUndefined()) 
 +            THROW_EXCEPTION(instr->attached.exceptionId);
 +
 +        QObject *object = registers[instr->attached.reg].getQObject();
 +        if (!object) {
 +            output.setUndefined();
 +        } else {
 +            QObject *attached = qmlAttachedPropertiesObjectById(instr->attached.id, input.getQObject(), true);
 +            Q_ASSERT(attached);
 +            output.setQObject(attached);
 +        }
 +    }
 +    QML_V4_END_INSTR(LoadAttached, attached)
 +
 +    QML_V4_BEGIN_INSTR(UnaryNot, unaryop)
 +    {
 +        registers[instr->unaryop.output].setbool(!registers[instr->unaryop.src].getbool());
 +    }
 +    QML_V4_END_INSTR(UnaryNot, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(UnaryMinusReal, unaryop)
 +    {
 +        registers[instr->unaryop.output].setqreal(-registers[instr->unaryop.src].getqreal());
 +    }
 +    QML_V4_END_INSTR(UnaryMinusReal, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop)
 +    {
 +        registers[instr->unaryop.output].setint(-registers[instr->unaryop.src].getint());
 +    }
 +    QML_V4_END_INSTR(UnaryMinusInt, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(UnaryPlusReal, unaryop)
 +    {
 +        registers[instr->unaryop.output].setqreal(+registers[instr->unaryop.src].getqreal());
 +    }
 +    QML_V4_END_INSTR(UnaryPlusReal, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop)
 +    {
 +        registers[instr->unaryop.output].setint(+registers[instr->unaryop.src].getint());
 +    }
 +    QML_V4_END_INSTR(UnaryPlusInt, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertBoolToInt, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) output.setUndefined();
 +        else output.setint(src.getbool());
 +    }
 +    QML_V4_END_INSTR(ConvertBoolToInt, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertBoolToReal, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) output.setUndefined();
 +        else output.setqreal(src.getbool());
 +    }
 +    QML_V4_END_INSTR(ConvertBoolToReal, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) {
 +            output.setUndefined();
 +        } else { 
 +            new (output.getstringptr()) QString(QLatin1String(src.getbool() ? "true" : "false"));
 +            STRING_REGISTER(instr->unaryop.output);
 +        }
 +    }
 +    QML_V4_END_INSTR(ConvertBoolToString, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertIntToBool, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) output.setUndefined();
 +        else output.setbool(src.getint());
 +    }
 +    QML_V4_END_INSTR(ConvertIntToBool, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertIntToReal, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) output.setUndefined();
 +        else output.setqreal(qreal(src.getint()));
 +    }
 +    QML_V4_END_INSTR(ConvertIntToReal, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) {
 +            output.setUndefined();
 +        } else { 
 +            new (output.getstringptr()) QString(QString::number(src.getint()));
 +            STRING_REGISTER(instr->unaryop.output);
 +        }
 +    }
 +    QML_V4_END_INSTR(ConvertIntToString, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertRealToBool, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) output.setUndefined();
 +        else output.setbool(src.getqreal() != 0);
 +    }
 +    QML_V4_END_INSTR(ConvertRealToBool, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertRealToInt, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) output.setUndefined();
 +        else output.setint(toInt32(src.getqreal()));
 +    }
 +    QML_V4_END_INSTR(ConvertRealToInt, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertRealToString, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        // ### NaN
 +        if (src.isUndefined()) {
 +            output.setUndefined();
 +        } else {
 +            new (output.getstringptr()) QString(QString::number(src.getqreal()));
 +            STRING_REGISTER(instr->unaryop.output);
 +        }
 +    }
 +    QML_V4_END_INSTR(ConvertRealToString, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        // ### NaN
 +        if (src.isUndefined()) {
 +            output.setUndefined();
 +        } else {
 +            // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
 +            // Ideally we should just call the methods in the QScript namespace directly.
 +            QJSValue tmp(*src.getstringptr());
 +            if (instr->unaryop.src == instr->unaryop.output) {
 +                output.cleanupString();
 +                MARK_CLEAN_REGISTER(instr->unaryop.output);
 +            }
 +            output.setbool(tmp.toBool());
 +        }
 +    }
 +    QML_V4_END_INSTR(ConvertStringToBool, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertStringToInt, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        // ### NaN
 +        if (src.isUndefined()) {
 +            output.setUndefined();
 +        } else {
 +            // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
 +            // Ideally we should just call the methods in the QScript namespace directly.
 +            QJSValue tmp(*src.getstringptr());
 +            if (instr->unaryop.src == instr->unaryop.output) {
 +                output.cleanupString();
 +                MARK_CLEAN_REGISTER(instr->unaryop.output);
 +            }
 +            output.setint(tmp.toInt());
 +        }
 +    }
 +    QML_V4_END_INSTR(ConvertStringToInt, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertStringToReal, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        // ### NaN
 +        if (src.isUndefined()) {
 +            output.setUndefined();
 +        } else {
 +            // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
 +            // Ideally we should just call the methods in the QScript namespace directly.
 +            QJSValue tmp(*src.getstringptr());
 +            if (instr->unaryop.src == instr->unaryop.output) {
 +                output.cleanupString();
 +                MARK_CLEAN_REGISTER(instr->unaryop.output);
 +            }
 +            output.setqreal(tmp.toNumber());
 +        }
 +    }
 +    QML_V4_END_INSTR(ConvertStringToReal, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        // ### NaN
 +        if (src.isUndefined()) {
 +            output.setUndefined();
 +        } else {
 +            const QString tmp(*src.getstringptr());
 +            if (instr->unaryop.src == instr->unaryop.output) {
 +                output.cleanupString();
 +                MARK_CLEAN_REGISTER(instr->unaryop.output);
 +            }
 +            QUrl *urlPtr = output.geturlptr();
 +            new (urlPtr) QUrl();
 +            urlPtr->setEncodedUrl(tmp.toUtf8(), QUrl::TolerantMode);
 +
 +            URL_REGISTER(instr->unaryop.output);
 +        }
 +    }
 +    QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
 +
++    QML_V4_BEGIN_INSTR(ConvertStringToColor, unaryop)
++    {
++        const Register &src = registers[instr->unaryop.src];
++        Register &output = registers[instr->unaryop.output];
++        // ### NaN
++        if (src.isUndefined()) {
++            output.setUndefined();
++        } else {
++            const QString tmp(*src.getstringptr());
++            if (instr->unaryop.src == instr->unaryop.output) {
++                output.cleanupString();
++                MARK_CLEAN_REGISTER(instr->unaryop.output);
++            }
++            QColor *colorPtr = output.getcolorptr();
++            new (colorPtr) QColor(QQmlStringConverters::colorFromString(tmp));
++
++            COLOR_REGISTER(instr->unaryop.output);
++        }
++    }
++    QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
++
 +    QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        // ### NaN
 +        if (src.isUndefined()) {
 +            output.setUndefined();
 +        } else {
 +            const QUrl tmp(*src.geturlptr());
 +            if (instr->unaryop.src == instr->unaryop.output) {
 +                output.cleanupUrl();
 +                MARK_CLEAN_REGISTER(instr->unaryop.output);
 +            }
 +            output.setbool(!tmp.isEmpty());
 +        }
 +    }
 +    QML_V4_END_INSTR(ConvertUrlToBool, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(ConvertUrlToString, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        // ### NaN
 +        if (src.isUndefined()) {
 +            output.setUndefined();
 +        } else {
 +            const QUrl tmp(*src.geturlptr());
 +            if (instr->unaryop.src == instr->unaryop.output) {
 +                output.cleanupUrl();
 +                MARK_CLEAN_REGISTER(instr->unaryop.output);
 +            }
 +            new (output.getstringptr()) QString(tmp.toString());
 +            STRING_REGISTER(instr->unaryop.output);
 +        }
 +    }
 +    QML_V4_END_INSTR(ConvertUrlToString, unaryop)
 +
++    QML_V4_BEGIN_INSTR(ConvertColorToBool, unaryop)
++    {
++        const Register &src = registers[instr->unaryop.src];
++        Register &output = registers[instr->unaryop.output];
++        // ### NaN
++        if (src.isUndefined()) {
++            output.setUndefined();
++        } else {
++            // for compatibility with color behavior in v8, always true
++            output.setbool(true);
++        }
++    }
++    QML_V4_END_INSTR(ConvertColorToBool, unaryop)
++
++    QML_V4_BEGIN_INSTR(ConvertColorToString, unaryop)
++    {
++        const Register &src = registers[instr->unaryop.src];
++        Register &output = registers[instr->unaryop.output];
++        // ### NaN
++        if (src.isUndefined()) {
++            output.setUndefined();
++        } else {
++            const QColor tmp(*src.getcolorptr());
++            if (instr->unaryop.src == instr->unaryop.output) {
++                output.cleanupColor();
++                MARK_CLEAN_REGISTER(instr->unaryop.output);
++            }
++            // to maintain behaviour with QtQuick 1.0, we just output normal toString() value.
++            new (output.getstringptr()) QString(QVariant(tmp).toString());
++            STRING_REGISTER(instr->unaryop.output);
++        }
++    }
++    QML_V4_END_INSTR(ConvertColorToString, unaryop)
++
 +    QML_V4_BEGIN_INSTR(ResolveUrl, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) {
 +            output.setUndefined();
 +        } else {
 +            const QUrl tmp(*src.geturlptr());
 +            if (instr->unaryop.src == instr->unaryop.output) {
 +                *output.geturlptr() = context->resolvedUrl(tmp);
 +            } else {
 +                new (output.geturlptr()) QUrl(context->resolvedUrl(tmp));
 +                URL_REGISTER(instr->unaryop.output);
 +            }
 +        }
 +    }
 +    QML_V4_END_INSTR(ResolveUrl, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(MathSinReal, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) output.setUndefined();
 +        else output.setqreal(qSin(src.getqreal()));
 +    }
 +    QML_V4_END_INSTR(MathSinReal, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(MathCosReal, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) output.setUndefined();
 +        else output.setqreal(qCos(src.getqreal()));
 +    }
 +    QML_V4_END_INSTR(MathCosReal, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(MathRoundReal, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) output.setUndefined();
 +        else output.setint(qRound(src.getqreal()));
 +    }
 +    QML_V4_END_INSTR(MathRoundReal, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(MathFloorReal, unaryop)
 +    {
 +        const Register &src = registers[instr->unaryop.src];
 +        Register &output = registers[instr->unaryop.output];
 +        if (src.isUndefined()) output.setUndefined();
 +        else output.setint(qFloor(src.getqreal()));
 +    }
 +    QML_V4_END_INSTR(MathFloorReal, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(MathPIReal, unaryop)
 +    {
 +        static const qreal qmlPI = 2.0 * qAsin(1.0);
 +        Register &output = registers[instr->unaryop.output];
 +        output.setqreal(qmlPI);
 +    }
 +    QML_V4_END_INSTR(MathPIReal, unaryop)
 +
 +    QML_V4_BEGIN_INSTR(LoadReal, real_value)
 +        registers[instr->real_value.reg].setqreal(instr->real_value.value);
 +    QML_V4_END_INSTR(LoadReal, real_value)
 +
 +    QML_V4_BEGIN_INSTR(LoadInt, int_value)
 +        registers[instr->int_value.reg].setint(instr->int_value.value);
 +    QML_V4_END_INSTR(LoadInt, int_value)
 +
 +    QML_V4_BEGIN_INSTR(LoadBool, bool_value)
 +        registers[instr->bool_value.reg].setbool(instr->bool_value.value);
 +    QML_V4_END_INSTR(LoadBool, bool_value)
 +
 +    QML_V4_BEGIN_INSTR(LoadString, string_value)
 +    {
 +        Register &output = registers[instr->string_value.reg];
 +        QChar *string = (QChar *)(data + instr->string_value.offset);
 +        new (output.getstringptr()) QString(string, instr->string_value.length);
 +        STRING_REGISTER(instr->string_value.reg);
 +    }
 +    QML_V4_END_INSTR(LoadString, string_value)
 +
 +    QML_V4_BEGIN_INSTR(EnableV4Test, string_value)
 +    {
 +        testBindingSource = new QString((QChar *)(data + instr->string_value.offset), instr->string_value.length);
 +        testBinding = true;
 +    }
 +    QML_V4_END_INSTR(String, string_value)
 +
 +    QML_V4_BEGIN_INSTR(BitAndInt, binaryop)
 +    {
 +        registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() & 
 +                                                 registers[instr->binaryop.right].getint());
 +    }
 +    QML_V4_END_INSTR(BitAndInt, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(BitOrInt, binaryop)
 +    {
 +        registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() | 
 +                                                 registers[instr->binaryop.right].getint());
 +    }
 +    QML_V4_END_INSTR(BitAndInt, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(BitXorInt, binaryop)
 +    {
 +        registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() ^ 
 +                                                 registers[instr->binaryop.right].getint());
 +    }
 +    QML_V4_END_INSTR(BitXorInt, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(AddReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() + 
 +                                                   registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(AddReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(AddString, binaryop)
 +    {
 +        QString &string = *registers[instr->binaryop.output].getstringptr();
 +        if (instr->binaryop.output == instr->binaryop.left) {
 +            string += registers[instr->binaryop.right].getstringptr();
 +        } else {
 +            string = *registers[instr->binaryop.left].getstringptr() + 
 +                     *registers[instr->binaryop.right].getstringptr();
 +        }
 +    }
 +    QML_V4_END_INSTR(AddString, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(SubReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() - 
 +                                                   registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(SubReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(MulReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() * 
 +                                                   registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(MulReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(DivReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() / 
 +                                                   registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(DivReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(ModReal, binaryop)
 +    {
 +        Register &target = registers[instr->binaryop.output];
 +        const Register &left = registers[instr->binaryop.left];
 +        const Register &right = registers[instr->binaryop.right];
 +        if (QMetaType::QReal == QMetaType::Float)
 +            target.setqreal(::fmodf(left.getqreal(), right.getqreal()));
 +        else
 +            target.setqreal(::fmod(left.getqreal(), right.getqreal()));
 +    }
 +    QML_V4_END_INSTR(ModInt, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(LShiftInt, binaryop)
 +    {
 +        registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() << 
 +                                                 registers[instr->binaryop.right].getint());
 +    }
 +    QML_V4_END_INSTR(LShiftInt, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(RShiftInt, binaryop)
 +    {
 +        registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() >> 
 +                                                 registers[instr->binaryop.right].getint());
 +    }
 +    QML_V4_END_INSTR(RShiftInt, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(URShiftInt, binaryop)
 +    {
 +        registers[instr->binaryop.output].setint((unsigned)registers[instr->binaryop.left].getint() >> 
 +                                                 registers[instr->binaryop.right].getint());
 +    }
 +    QML_V4_END_INSTR(URShiftInt, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(GtReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() > 
 +                                                  registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(GtReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(LtReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() < 
 +                                                  registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(LtReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(GeReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >= 
 +                                                  registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(GeReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(LeReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <= 
 +                                                  registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(LeReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(EqualReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == 
 +                                                  registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(EqualReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(NotEqualReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != 
 +                                                  registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(NotEqualReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(StrictEqualReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() == 
 +                                                  registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(StrictEqualReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(StrictNotEqualReal, binaryop)
 +    {
 +        registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() != 
 +                                                  registers[instr->binaryop.right].getqreal());
 +    }
 +    QML_V4_END_INSTR(StrictNotEqualReal, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(GtString, binaryop)
 +    {
 +        const QString &a = *registers[instr->binaryop.left].getstringptr();
 +        const QString &b = *registers[instr->binaryop.right].getstringptr();
 +        bool result = a > b;
 +        if (instr->binaryop.left == instr->binaryop.output) {
 +            registers[instr->binaryop.output].cleanupString();
 +            MARK_CLEAN_REGISTER(instr->binaryop.output);
 +        }
 +        registers[instr->binaryop.output].setbool(result);
 +    }
 +    QML_V4_END_INSTR(GtString, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(LtString, binaryop)
 +    {
 +        const QString &a = *registers[instr->binaryop.left].getstringptr();
 +        const QString &b = *registers[instr->binaryop.right].getstringptr();
 +        bool result = a < b;
 +        if (instr->binaryop.left == instr->binaryop.output) {
 +            registers[instr->binaryop.output].cleanupString();
 +            MARK_CLEAN_REGISTER(instr->binaryop.output);
 +        }
 +        registers[instr->binaryop.output].setbool(result);
 +    }
 +    QML_V4_END_INSTR(LtString, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(GeString, binaryop)
 +    {
 +        const QString &a = *registers[instr->binaryop.left].getstringptr();
 +        const QString &b = *registers[instr->binaryop.right].getstringptr();
 +        bool result = a >= b;
 +        if (instr->binaryop.left == instr->binaryop.output) {
 +            registers[instr->binaryop.output].cleanupString();
 +            MARK_CLEAN_REGISTER(instr->binaryop.output);
 +        }
 +        registers[instr->binaryop.output].setbool(result);
 +    }
 +    QML_V4_END_INSTR(GeString, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(LeString, binaryop)
 +    {
 +        const QString &a = *registers[instr->binaryop.left].getstringptr();
 +        const QString &b = *registers[instr->binaryop.right].getstringptr();
 +        bool result = a <= b;
 +        if (instr->binaryop.left == instr->binaryop.output) {
 +            registers[instr->binaryop.output].cleanupString();
 +            MARK_CLEAN_REGISTER(instr->binaryop.output);
 +        }
 +        registers[instr->binaryop.output].setbool(result);
 +    }
 +    QML_V4_END_INSTR(LeString, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(EqualString, binaryop)
 +    {
 +        const QString &a = *registers[instr->binaryop.left].getstringptr();
 +        const QString &b = *registers[instr->binaryop.right].getstringptr();
 +        bool result = a == b;
 +        if (instr->binaryop.left == instr->binaryop.output) {
 +            registers[instr->binaryop.output].cleanupString();
 +            MARK_CLEAN_REGISTER(instr->binaryop.output);
 +        }
 +        registers[instr->binaryop.output].setbool(result);
 +    }
 +    QML_V4_END_INSTR(EqualString, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(NotEqualString, binaryop)
 +    {
 +        const QString &a = *registers[instr->binaryop.left].getstringptr();
 +        const QString &b = *registers[instr->binaryop.right].getstringptr();
 +        bool result = a != b;
 +        if (instr->binaryop.left == instr->binaryop.output) {
 +            registers[instr->binaryop.output].cleanupString();
 +            MARK_CLEAN_REGISTER(instr->binaryop.output);
 +        }
 +        registers[instr->binaryop.output].setbool(result);
 +    }
 +    QML_V4_END_INSTR(NotEqualString, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(StrictEqualString, binaryop)
 +    {
 +        const QString &a = *registers[instr->binaryop.left].getstringptr();
 +        const QString &b = *registers[instr->binaryop.right].getstringptr();
 +        bool result = a == b;
 +        if (instr->binaryop.left == instr->binaryop.output) {
 +            registers[instr->binaryop.output].cleanupString();
 +            MARK_CLEAN_REGISTER(instr->binaryop.output);
 +        }
 +        registers[instr->binaryop.output].setbool(result);
 +    }
 +    QML_V4_END_INSTR(StrictEqualString, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(StrictNotEqualString, binaryop)
 +    {
 +        const QString &a = *registers[instr->binaryop.left].getstringptr();
 +        const QString &b = *registers[instr->binaryop.right].getstringptr();
 +        bool result = a != b;
 +        if (instr->binaryop.left == instr->binaryop.output) {
 +            registers[instr->binaryop.output].cleanupString();
 +            MARK_CLEAN_REGISTER(instr->binaryop.output);
 +        }
 +        registers[instr->binaryop.output].setbool(result);
 +    }
 +    QML_V4_END_INSTR(StrictNotEqualString, binaryop)
 +
 +    QML_V4_BEGIN_INSTR(NewString, construct)
 +    {
 +        Register &output = registers[instr->construct.reg];
 +        new (output.getstringptr()) QString;
 +        STRING_REGISTER(instr->construct.reg);
 +    }
 +    QML_V4_END_INSTR(NewString, construct)
 +
 +    QML_V4_BEGIN_INSTR(NewUrl, construct)
 +    {
 +        Register &output = registers[instr->construct.reg];
 +        new (output.geturlptr()) QUrl;
 +        URL_REGISTER(instr->construct.reg);
 +    }
 +    QML_V4_END_INSTR(NewUrl, construct)
 +
 +    QML_V4_BEGIN_INSTR(Fetch, fetch)
 +    {
 +        Register &reg = registers[instr->fetch.reg];
 +
 +        if (reg.isUndefined()) 
 +            THROW_EXCEPTION(instr->fetch.exceptionId);
 +
 +        QObject *object = reg.getQObject();
 +        if (!object) {
 +            THROW_EXCEPTION(instr->fetch.exceptionId);
 +        } else {
 +            reg.init((Register::Type)instr->fetch.valueType);
 +            if (instr->fetch.valueType >= FirstCleanupType)
 +                MARK_REGISTER(instr->fetch.reg);
 +            void *argv[] = { reg.typeDataPtr(), 0 };
 +            QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv);
 +        }
 +    }
 +    QML_V4_END_INSTR(Fetch, fetch)
 +
 +    QML_V4_BEGIN_INSTR(TestV4Store, storetest)
 +    {
 +        Register &data = registers[instr->storetest.reg];
 +        testBindingResult(*testBindingSource, bindingLine, bindingColumn, context, 
 +                          scope, data, instr->storetest.regType);
 +    }
 +    QML_V4_END_INSTR(TestV4Store, storetest)
 +
 +    QML_V4_BEGIN_INSTR(Store, store)
 +    {
 +        Register &data = registers[instr->store.reg];
 +
 +        if (data.isUndefined()) 
 +            THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value"));
 +
 +        int status = -1;
 +        void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags };
 +        QMetaObject::metacall(output, QMetaObject::WriteProperty,
 +                              instr->store.index, argv);
 +
 +        goto programExit;
 +    }
 +    QML_V4_END_INSTR(Store, store)
 +
 +    QML_V4_BEGIN_INSTR(Copy, copy)
 +        registers[instr->copy.reg].copy(registers[instr->copy.src]);
 +        if (registers[instr->copy.reg].gettype() >= FirstCleanupType)
 +            MARK_REGISTER(instr->copy.reg);
 +    QML_V4_END_INSTR(Copy, copy)
 +
 +    QML_V4_BEGIN_INSTR(Jump, jump)
 +        if (instr->jump.reg == -1 || !registers[instr->jump.reg].getbool())
 +            code += instr->jump.count;
 +    QML_V4_END_INSTR(Jump, jump)
 +
 +    QML_V4_BEGIN_INSTR(BranchTrue, branchop)
 +        if (registers[instr->branchop.reg].getbool())
 +            code += instr->branchop.offset;
 +    QML_V4_END_INSTR(BranchTrue, branchop)
 +
 +    QML_V4_BEGIN_INSTR(BranchFalse, branchop)
 +        if (! registers[instr->branchop.reg].getbool())
 +            code += instr->branchop.offset;
 +    QML_V4_END_INSTR(BranchFalse, branchop)
 +
 +    QML_V4_BEGIN_INSTR(Branch, branchop)
 +        code += instr->branchop.offset;
 +    QML_V4_END_INSTR(Branch, branchop)
 +
 +    QML_V4_BEGIN_INSTR(Block, blockop)
 +        executedBlocks |= instr->blockop.block;
 +    QML_V4_END_INSTR(Block, blockop)
 +
 +    // XXX not applicable in v8
 +    QML_V4_BEGIN_INSTR(InitString, initstring)
 +//        if (!identifiers[instr->initstring.offset].identifier) {
 +//            quint32 len = *(quint32 *)(data + instr->initstring.dataIdx);
 +//            QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32));
 +
 +//            QString str = QString::fromRawData(strdata, len);
 +
 +//            // identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
 +//        }
 +    QML_V4_END_INSTR(InitString, initstring)
 +
 +    QML_V4_BEGIN_INSTR(CleanupRegister, cleanup)
 +        registers[instr->cleanup.reg].cleanup();
 +    QML_V4_END_INSTR(CleanupRegister, cleanup)
 +
 +#ifdef QML_THREADED_INTERPRETER
 +    // nothing to do
 +#else
 +    default:
 +        qFatal("QV4: Unknown instruction %d encountered.", instr->common.type);
 +        break;
 +    } // switch
 +
 +    } // while
 +#endif
 +
 +    Q_ASSERT(!"Unreachable code reached");
 +
 +programExit:
 +exceptionExit:
 +    delete testBindingSource;
 +
 +    int reg = 0;
 +    while (cleanupRegisterMask) {
 +        if (cleanupRegisterMask & 0x1) 
 +            registers[reg].cleanup();
 +
 +        reg++;
 +        cleanupRegisterMask >>= 1;
 +    }
 +}
 +
 +QT_END_NAMESPACE
index 61d29a6,0000000..1824fa4
mode 100644,000000..100644
--- /dev/null
@@@ -1,153 -1,0 +1,155 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QV4BINDINGS_P_H
 +#define QV4BINDINGS_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/qqmlexpression_p.h"
 +#include "private/qqmlbinding_p.h"
 +#include "private/qv4instruction_p.h"
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +struct QV4Program;
 +class QV4Bindings : public QQmlAbstractExpression, 
 +                               public QQmlRefCount
 +{
 +    Q_DECLARE_TR_FUNCTIONS(QV4Bindings)
 +public:
 +    QV4Bindings(const char *program, QQmlContextData *context,
 +                           QQmlRefCount *);
 +    virtual ~QV4Bindings();
 +
 +    QQmlAbstractBinding *configBinding(int index, QObject *target, 
 +                                               QObject *scope, int property,
 +                                               int line, int column);
 +
 +#ifdef QML_THREADED_INTERPRETER
 +    static void **getDecodeInstrTable();
 +#endif
 +
 +private:
 +    Q_DISABLE_COPY(QV4Bindings)
 +
 +    struct Binding : public QQmlAbstractBinding, public QQmlDelayedError {
 +        Binding() : enabled(false), updating(0), property(0),
 +                    scope(0), target(0), executedBlocks(0), parent(0) {}
 +
 +        // Inherited from QQmlAbstractBinding
 +        virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags);
 +        virtual void update(QQmlPropertyPrivate::WriteFlags flags);
 +        virtual void destroy();
 +        virtual int propertyIndex() const;
 +        virtual QObject *object() const;
 +
 +        int index:30;
 +        bool enabled:1;
 +        bool updating:1;
++        // Encoding of property is coreIndex | (propType << 16) | (valueTypeIndex << 24)
++        // propType and valueTypeIndex are only set if the property is a value type property
 +        int property;
 +        QObject *scope;
 +        int line;
 +        int column;
 +        QObject *target;
 +        quint32 executedBlocks;
 +
 +        QV4Bindings *parent;
 +    };
 +
 +    class Subscription : public QQmlNotifierEndpoint
 +    {
 +    public:
 +        Subscription() : bindings(0), method(-1) { callback = &subscriptionCallback; }
 +        static void subscriptionCallback(QQmlNotifierEndpoint *e);
 +        QV4Bindings *bindings;
 +        int method;
 +    };
 +    friend class Subscription;
 +
 +    Subscription *subscriptions;
 +
 +    void subscriptionNotify(int);
 +    void run(Binding *, QQmlPropertyPrivate::WriteFlags flags);
 +
 +    QV4Program *program;
 +    QQmlRefCount *dataRef;
 +    Binding *bindings;
 +
 +    void init();
 +    void run(int instr, quint32 &executedBlocks, QQmlContextData *context,
 +             QQmlDelayedError *error, QObject *scope, QObject *output, 
 +             QQmlPropertyPrivate::WriteFlags storeFlags
 +#ifdef QML_THREADED_INTERPRETER
 +             , void ***decode_instr = 0
 +#endif
 +             );
 +
 +
 +    inline void unsubscribe(int subIndex);
 +    inline void subscribeId(QQmlContextData *p, int idIndex, int subIndex);
 +    inline void subscribe(QObject *o, int notifyIndex, int subIndex);
 +
 +    inline static qint32 toInt32(qreal n);
 +    static const qreal D32;
 +    static quint32 toUint32(qreal n);
 +
 +};
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QV4BINDINGS_P_H
 +
index d61fd58,0000000..f8fe3b4
mode 100644,000000..100644
--- /dev/null
@@@ -1,1399 -1,0 +1,1420 @@@
- : _function(0) , _block(0) , _discarded(false)
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qv4compiler_p.h"
 +#include "qv4compiler_p_p.h"
 +#include "qv4program_p.h"
 +#include "qv4ir_p.h"
 +#include "qv4irbuilder_p.h"
 +
 +#include <private/qqmlglobal_p.h>
 +#include <private/qqmljsast_p.h>
 +#include <private/qqmlaccessors_p.h>
 +#include <private/qqmljsengine_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP)
 +DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER)
 +DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL)
 +DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
 +DEFINE_BOOL_CONFIG_OPTION(qmlBindingsTestEnv, QML_BINDINGS_TEST)
 +
 +static bool qmlBindingsTest = false;
 +static bool qmlEnableV4 = true;
 +
 +using namespace QQmlJS;
 +QV4CompilerPrivate::QV4CompilerPrivate()
-     if (discarded || subscriptionIds.count() > 0xFFFF || registeredStrings.count() > 0xFFFF)
++    : _function(0) , _block(0) , _discarded(false), registerCount(0)
 +{
 +}
 +
 +//
 +// tracing
 +//
 +void QV4CompilerPrivate::trace(int line, int column)
 +{
 +    bytecode.clear();
 +
 +    this->currentReg = _function->tempCount;
++    this->registerCount = qMax(this->registerCount, this->currentReg);
 +
 +    foreach (IR::BasicBlock *bb, _function->basicBlocks) {
 +        if (! bb->isTerminated() && (bb->index + 1) < _function->basicBlocks.size())
 +            bb->JUMP(_function->basicBlocks.at(bb->index + 1));
 +    }
 +
 +    QVector<IR::BasicBlock *> blocks;
 +    trace(&blocks);
 +    currentBlockMask = 0x00000001;
 +
 +
 +    for (int i = 0; !_discarded && i < blocks.size(); ++i) {
 +        IR::BasicBlock *block = blocks.at(i);
 +        IR::BasicBlock *next = i + 1 < blocks.size() ? blocks.at(i + 1) : 0;
 +        if (IR::Stmt *terminator = block->terminator()) {
 +            if (IR::CJump *cj = terminator->asCJump()) {
 +                if (cj->iffalse != next) {
 +                    IR::Jump *jump = _function->pool->New<IR::Jump>();
 +                    jump->init(cj->iffalse);
 +                    block->statements.append(jump);
 +                }
 +            } else if (IR::Jump *j = terminator->asJump()) {
 +                if (j->target == next) {
 +                    block->statements.resize(block->statements.size() - 1);
 +                }
 +            }
 +        }
 +
 +        block->offset = bytecode.size();
 +
 +        if (bytecode.isEmpty()) {
 +            if (qmlBindingsTest || bindingsDump()) {
 +                Instr::BindingId id;
 +                id.column = column;
 +                id.line = line;
 +                gen(id);
 +            }
 +
 +            if (qmlBindingsTest) {
 +                QString str = expression->expression.asScript();
 +                QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar));
 +                int offset = data.count();
 +                data += strdata;
 +
 +                Instr::EnableV4Test test;
 +                test.reg = 0;
 +                test.offset = offset;
 +                test.length = str.length();
 +                gen(test);
 +            }
 +        }
 +
 +        bool usic = false;
 +        int patchesCount = patches.count();
 +        qSwap(usedSubscriptionIdsChanged, usic);
 +
 +        int blockopIndex = bytecode.size();
 +        Instr::Block blockop;
 +        blockop.block = currentBlockMask;
 +        gen(blockop);
 +
 +        foreach (IR::Stmt *s, block->statements) {
 +            if (! _discarded)
 +                s->accept(this);
 +        }
 +
 +        qSwap(usedSubscriptionIdsChanged, usic);
 +
 +        if (usic) {
 +            if (currentBlockMask == 0x80000000) {
 +                discard();
 +                return;
 +            }
 +            currentBlockMask <<= 1;
 +        } else if (! _discarded) {
 +            const int adjust = bytecode.remove(blockopIndex);
 +            // Correct patches
 +            for (int ii = patchesCount; ii < patches.count(); ++ii) 
 +                patches[ii].offset -= adjust;
 +        }
 +    }
 +
 +#ifdef DEBUG_IR_STRUCTURE
 +    IR::IRDump dump;
 +    for (int i = 0; i < blocks.size(); ++i) {
 +        dump.basicblock(blocks.at(i));
 +    }
 +#endif
 +
 +
 +    if (! _discarded) {
 +        // back patching
 +        foreach (const Patch &patch, patches) {
 +            V4Instr &instr = bytecode[patch.offset];
 +            int size = V4Instr::size(instructionType(&instr));
 +            instr.branchop.offset = patch.block->offset - patch.offset - size;
 +        }
 +
 +        patches.clear();
 +    }
 +}
 +
 +void QV4CompilerPrivate::trace(QVector<IR::BasicBlock *> *blocks)
 +{
 +    for (int i = 0; i < _function->basicBlocks.size(); ++i) {
 +        IR::BasicBlock *block = _function->basicBlocks.at(i);
 +
 +        while (! blocks->contains(block)) {
 +            blocks->append(block);
 +
 +            if (IR::Stmt *terminator = block->terminator()) {
 +                if (IR::CJump *cj = terminator->asCJump())
 +                    block = cj->iffalse;
 +                else if (IR::Jump *j = terminator->asJump())
 +                    block = j->target;
 +            }
 +        }
 +    }
 +}
 +
 +void QV4CompilerPrivate::traceExpression(IR::Expr *e, quint8 r)
 +{
 +    if (!e) {
 +        discard();
 +    } else {
 +        qSwap(currentReg, r);
 +        e->accept(this);
 +        qSwap(currentReg, r);
 +    }
 +}
 +
 +//
 +// expressions
 +//
 +void QV4CompilerPrivate::visitConst(IR::Const *e)
 +{
 +    switch (e->type) {
 +    case IR::BoolType: {
 +        Instr::LoadBool i;
 +        i.reg = currentReg;
 +        i.value = e->value;
 +        gen(i);
 +        } break;
 +
 +    case IR::IntType: {
 +        Instr::LoadInt i;
 +        i.reg = currentReg;
 +        i.value = e->value;
 +        gen(i);
 +        } break;
 +
 +    case IR::RealType: {
 +        Instr::LoadReal i;
 +        i.reg = currentReg;
 +        i.value = e->value;
 +        gen(i);
 +        } break;
 +
 +    default:
 +        if (qmlVerboseCompiler())
 +            qWarning() << Q_FUNC_INFO << "unexpected type";
 +        discard();
 +    }
 +}
 +
 +void QV4CompilerPrivate::visitString(IR::String *e)
 +{
 +    registerLiteralString(currentReg, e->value);
 +}
 +
 +void QV4CompilerPrivate::visitName(IR::Name *e)
 +{
 +    if (e->base) {
 +        // fetch the object and store it in reg.
 +        traceExpression(e->base, currentReg);
 +    } else {
 +        _subscribeName.clear();
 +    }
 +
 +    if (e->storage == IR::Name::RootStorage) {
 +
 +        Instr::LoadRoot instr;
 +        instr.reg = currentReg;
 +        gen(instr);
 +
 +        if (e->symbol == IR::Name::IdObject) {
 +            // The ID is a reference to the root object
 +            return;
 +        }
 +
 +    } else if (e->storage == IR::Name::ScopeStorage) {
 +
 +        Instr::LoadScope instr;
 +        instr.reg = currentReg;
 +        gen(instr);
 +
 +        _subscribeName << contextName();
 +
 +    } else if (e->storage == IR::Name::IdStorage) {
 +
 +        Instr::LoadId instr;
 +        instr.reg = currentReg;
 +        instr.index = e->idObject->idIndex;
 +        gen(instr);
 +
 +        _subscribeName << QLatin1String("$$$ID_") + *e->id;
 +
 +        if (blockNeedsSubscription(_subscribeName)) {
 +            Instr::SubscribeId sub;
 +            sub.reg = currentReg;
 +            sub.offset = subscriptionIndex(_subscribeName);
 +            sub.index = instr.index;
 +            gen(sub);
 +        }
 +
 +        return;
 +    } else {
 +        // No action needed
 +    }
 +
 +    switch (e->symbol) {
 +    case IR::Name::Unbound: 
 +    case IR::Name::IdObject: 
 +    case IR::Name::Slot:
 +    case IR::Name::Object: {
 +        Q_ASSERT(!"Unreachable");
 +        discard();
 +    } break;
 +
 +    case IR::Name::AttachType: {
 +        _subscribeName << *e->id;
 +
 +        Instr::LoadAttached attached;
 +        attached.output = currentReg;
 +        attached.reg = currentReg;
 +        attached.exceptionId = exceptionId(e->line, e->column);
 +        if (e->declarativeType->attachedPropertiesId() == -1)
 +            discard();
 +        attached.id = e->declarativeType->attachedPropertiesId();
 +        gen(attached);
 +    } break;
 +
 +    case IR::Name::Property: {
 +        _subscribeName << *e->id;
 +
 +        if (e->property->coreIndex == -1) {
 +            QMetaProperty prop;
 +            e->property->load(prop, QQmlEnginePrivate::get(engine));
 +        }
 +
 +        const int propTy = e->property->propType;
 +        QQmlRegisterType regType;
 +
 +        switch (propTy) {
 +        case QMetaType::QReal:
 +            regType = QRealType;
 +            break;
 +        case QMetaType::Bool:
 +            regType = BoolType;
 +            break;
 +        case QMetaType::Int:
 +            regType = IntType;
 +            break;
 +        case QMetaType::QString:
 +            regType = QStringType;
 +            break;
 +        case QMetaType::QUrl:
 +            regType = QUrlType;
 +            break;
++        case QMetaType::QColor:
++            regType = QColorType;
++            break;
 +
 +        default:
 +            if (propTy == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
 +                regType = PODValueType;
 +            } else if (QQmlMetaType::isQObject(propTy)) {
 +                regType = QObjectStarType;
 +            } else {
 +                if (qmlVerboseCompiler())
 +                    qWarning() << "Discard unsupported property type:" << QMetaType::typeName(propTy);
 +                discard(); // Unsupported type
 +                return;
 +            }
 +
 +            break;
 +        } // switch
 +
 +        if (e->property->hasAccessors()) {
 +            Instr::FetchAndSubscribe fetch;
 +            fetch.reg = currentReg;
 +            fetch.subscription = subscriptionIndex(_subscribeName);
 +            fetch.exceptionId = exceptionId(e->line, e->column);
 +            fetch.valueType = regType;
 +            fetch.property = *e->property;
 +            gen(fetch);
 +        } else {
 +            if (blockNeedsSubscription(_subscribeName) && e->property->notifyIndex != -1) {
 +                Instr::Subscribe sub;
 +                sub.reg = currentReg;
 +                sub.offset = subscriptionIndex(_subscribeName);
 +                sub.index = e->property->notifyIndex;
 +                gen(sub);
 +            }
 +
 +            Instr::Fetch fetch;
 +            fetch.reg = currentReg;
 +            fetch.index = e->property->coreIndex;
 +            fetch.exceptionId = exceptionId(e->line, e->column);
 +            fetch.valueType = regType;
 +            gen(fetch);
 +        }
 +
 +    } break;
 +    } // switch
 +}
 +
 +void QV4CompilerPrivate::visitTemp(IR::Temp *e)
 +{
 +    if (currentReg != e->index) {
 +        Instr::Copy i;
 +        i.reg = currentReg;
 +        i.src = e->index;
 +        gen(i);
 +    }
 +}
 +
 +void QV4CompilerPrivate::visitUnop(IR::Unop *e)
 +{
 +    quint8 src = currentReg;
 +    
 +    if (IR::Temp *temp = e->expr->asTemp()) {
 +        src = temp->index;
 +    } else {
 +        traceExpression(e->expr, src);
 +    }
 +
 +    switch (e->op) {
 +    case IR::OpInvalid:
 +        Q_ASSERT(!"unreachable");
 +        break;
 +
 +    case IR::OpIfTrue:
 +        convertToBool(e->expr, src);
 +        if (src != currentReg) {
 +            Instr::Copy i;
 +            i.reg = currentReg;
 +            i.src = src;
 +            gen(i);
 +        }
 +        break;
 +
 +    case IR::OpNot: {
 +        Instr::UnaryNot i;
 +        convertToBool(e->expr, src);
 +        i.output = currentReg;
 +        i.src = src;
 +        gen(i);
 +        } break;
 +
 +    case IR::OpUMinus:
 +        if (e->expr->type == IR::RealType) {
 +            Instr::UnaryMinusReal i;
 +            i.output = currentReg;
 +            i.src = src;
 +            gen(i);
 +        } else if (e->expr->type == IR::IntType) {
 +            convertToReal(e->expr, currentReg);
 +            Instr::UnaryMinusReal i;
 +            i.output = currentReg;
 +            i.src = src;
 +            gen(i);
 +        } else {
 +            discard();
 +        }
 +        break;
 +
 +    case IR::OpUPlus:
 +        if (e->expr->type == IR::RealType) {
 +            Instr::UnaryPlusReal i;
 +            i.output = currentReg;
 +            i.src = src;
 +            gen(i);
 +        } else if (e->expr->type == IR::IntType) {
 +            convertToReal(e->expr, currentReg);
 +            Instr::UnaryPlusReal i;
 +            i.output = currentReg;
 +            i.src = src;
 +            gen(i);
 +        } else {
 +            discard();
 +        }
 +        break;
 +
 +    case IR::OpCompl:
 +        // TODO
 +        discard();
 +        break;
 +
 +    case IR::OpBitAnd:
 +    case IR::OpBitOr:
 +    case IR::OpBitXor:
 +    case IR::OpAdd:
 +    case IR::OpSub:
 +    case IR::OpMul:
 +    case IR::OpDiv:
 +    case IR::OpMod:
 +    case IR::OpLShift:
 +    case IR::OpRShift:
 +    case IR::OpURShift:
 +    case IR::OpGt:
 +    case IR::OpLt:
 +    case IR::OpGe:
 +    case IR::OpLe:
 +    case IR::OpEqual:
 +    case IR::OpNotEqual:
 +    case IR::OpStrictEqual:
 +    case IR::OpStrictNotEqual:
 +    case IR::OpAnd:
 +    case IR::OpOr:
 +        Q_ASSERT(!"unreachable");
 +        break;
 +    } // switch
 +}
 +
 +void QV4CompilerPrivate::convertToReal(IR::Expr *expr, int reg)
 +{
 +    if (expr->type == IR::RealType)
 +        return;
 +
 +    switch (expr->type) {
 +    case IR::BoolType: {
 +        Instr::ConvertBoolToReal i;
 +        i.output = i.src = reg;
 +        gen(i);
 +        } break;
 +
 +    case IR::IntType: {
 +        Instr::ConvertIntToReal i;
 +        i.output = i.src = reg;
 +        gen(i);
 +        } break;
 +
 +    case IR::RealType:
 +        // nothing to do
 +        return;
 +
 +    default:
 +        discard();
 +        break;
 +    } // switch
 +}
 +
 +void QV4CompilerPrivate::convertToInt(IR::Expr *expr, int reg)
 +{
 +    if (expr->type == IR::IntType)
 +        return;
 +
 +    switch (expr->type) {
 +    case IR::BoolType: {
 +        Instr::ConvertBoolToInt i;
 +        i.output = i.src = reg;
 +        gen(i);
 +        } break;
 +
 +    case IR::IntType:
 +        // nothing to do
 +        return;
 +
 +    case IR::RealType: {
 +        Instr::ConvertRealToInt i;
 +        i.output = i.src = reg;
 +        gen(i);
 +        } break;
 +
 +    default:
 +        discard();
 +        break;
 +    } // switch
 +}
 +
 +void QV4CompilerPrivate::convertToBool(IR::Expr *expr, int reg)
 +{
 +    if (expr->type == IR::BoolType)
 +        return;
 +
 +    switch (expr->type) {
 +    case IR::BoolType:
 +        // nothing to do
 +        break;
 +
 +    case IR::IntType: {
 +        Instr::ConvertIntToBool i;
 +        i.output = i.src = reg;
 +        gen(i);
 +        } break;
 +
 +    case IR::RealType: {
 +        Instr::ConvertRealToBool i;
 +        i.output = i.src = reg;
 +        gen(i);
 +        } return;
 +
 +    case IR::StringType: {
 +        Instr::ConvertStringToBool i;
 +        i.output = i.src = reg;
 +        gen(i);
 +        } return;
 +
++    case IR::ColorType: {
++        Instr::ConvertColorToBool i;
++        i.output = i.src = reg;
++        gen(i);
++        } return;
++
 +    default:
 +        discard();
 +        break;
 +    } // switch
 +}
 +
 +quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e)
 +{
 +    switch (e->op) {
 +    case IR::OpInvalid:
 +        return V4Instr::Noop;
 +
 +    case IR::OpIfTrue:
 +    case IR::OpNot:
 +    case IR::OpUMinus:
 +    case IR::OpUPlus:
 +    case IR::OpCompl:
 +        return V4Instr::Noop;
 +
 +    case IR::OpBitAnd:
 +        return V4Instr::BitAndInt;
 +
 +    case IR::OpBitOr:
 +        return V4Instr::BitOrInt;
 +
 +    case IR::OpBitXor:
 +        return V4Instr::BitXorInt;
 +
 +    case IR::OpAdd:
 +        if (e->type == IR::StringType)
 +            return V4Instr::AddString;
 +        return V4Instr::AddReal;
 +
 +    case IR::OpSub:
 +        return V4Instr::SubReal;
 +
 +    case IR::OpMul:
 +        return V4Instr::MulReal;
 +
 +    case IR::OpDiv:
 +        return V4Instr::DivReal;
 +
 +    case IR::OpMod:
 +        return V4Instr::ModReal;
 +
 +    case IR::OpLShift:
 +        return V4Instr::LShiftInt;
 +
 +    case IR::OpRShift:
 +        return V4Instr::RShiftInt;
 +
 +    case IR::OpURShift:
 +        return V4Instr::URShiftInt;
 +
 +    case IR::OpGt:
 +        if (e->left->type == IR::StringType)
 +            return V4Instr::GtString;
 +        return V4Instr::GtReal;
 +
 +    case IR::OpLt:
 +        if (e->left->type == IR::StringType)
 +            return V4Instr::LtString;
 +        return V4Instr::LtReal;
 +
 +    case IR::OpGe:
 +        if (e->left->type == IR::StringType)
 +            return V4Instr::GeString;
 +        return V4Instr::GeReal;
 +
 +    case IR::OpLe:
 +        if (e->left->type == IR::StringType)
 +            return V4Instr::LeString;
 +        return V4Instr::LeReal;
 +
 +    case IR::OpEqual:
 +        if (e->left->type == IR::StringType)
 +            return V4Instr::EqualString;
 +        return V4Instr::EqualReal;
 +
 +    case IR::OpNotEqual:
 +        if (e->left->type == IR::StringType)
 +            return V4Instr::NotEqualString;
 +        return V4Instr::NotEqualReal;
 +
 +    case IR::OpStrictEqual:
 +        if (e->left->type == IR::StringType)
 +            return V4Instr::StrictEqualString;
 +        return V4Instr::StrictEqualReal;
 +
 +    case IR::OpStrictNotEqual:
 +        if (e->left->type == IR::StringType)
 +            return V4Instr::StrictNotEqualString;
 +        return V4Instr::StrictNotEqualReal;
 +
 +    case IR::OpAnd:
 +    case IR::OpOr:
 +        return V4Instr::Noop;
 +
 +    } // switch
 +
 +    return V4Instr::Noop;
 +}
 +
 +void QV4CompilerPrivate::visitBinop(IR::Binop *e)
 +{
 +    int left = currentReg;
 +    int right = currentReg + 1; 
 +
 +    if (e->left->asTemp() && e->type != IR::StringType)  // Not sure if the e->type != String test is needed
 +        left = e->left->asTemp()->index;
 +    else
 +        traceExpression(e->left, left);
 +
 +    if (IR::Temp *t = e->right->asTemp())
 +        right = t->index;
 +    else
 +        traceExpression(e->right, right);
 +
 +    if (e->left->type != e->right->type) {
 +        if (qmlVerboseCompiler())
 +            qWarning().nospace() << "invalid operands to binary operator " << IR::binaryOperator(e->op)
 +                                 << "(`" << IR::binaryOperator(e->left->type)
 +                                 << "' and `"
 +                                 << IR::binaryOperator(e->right->type)
 +                                 << "'";
 +        discard();
 +        return;
 +    }
 +
 +    switch (e->op) {
 +    case IR::OpInvalid:
 +        discard();
 +        break;
 +
 +    // unary
 +    case IR::OpIfTrue:
 +    case IR::OpNot:
 +    case IR::OpUMinus:
 +    case IR::OpUPlus:
 +    case IR::OpCompl:
 +        discard();
 +        break;
 +
 +    case IR::OpBitAnd:
 +    case IR::OpBitOr:
 +    case IR::OpBitXor:
 +    case IR::OpLShift:
 +    case IR::OpRShift:
 +    case IR::OpURShift:
 +        convertToInt(e->left, left);
 +        convertToInt(e->right, right);
 +        break;
 +
 +    case IR::OpAdd:
 +        if (e->type != IR::StringType) {
 +            convertToReal(e->left, left);
 +            convertToReal(e->right, right);
 +        }
 +        break;
 +
 +    case IR::OpSub:
 +    case IR::OpMul:
 +    case IR::OpDiv:
 +    case IR::OpMod:
 +        convertToReal(e->left, left);
 +        convertToReal(e->right, right);
 +        break;
 +
 +    case IR::OpGt:
 +    case IR::OpLt:
 +    case IR::OpGe:
 +    case IR::OpLe:
 +    case IR::OpEqual:
 +    case IR::OpNotEqual:
 +    case IR::OpStrictEqual:
 +    case IR::OpStrictNotEqual:
 +        if (e->left->type != IR::StringType) {
 +            convertToReal(e->left, left);
 +            convertToReal(e->right, right);
 +        }
 +        break;
 +
 +    case IR::OpAnd:
 +    case IR::OpOr:
 +        discard(); // ### unreachable
 +        break;
 +    } // switch
 +
 +    const quint8 opcode = instructionOpcode(e);
 +    if (opcode != V4Instr::Noop) {
 +        V4Instr instr;
 +        instr.binaryop.output = currentReg;
 +        instr.binaryop.left = left;
 +        instr.binaryop.right = right;
 +        gen(static_cast<V4Instr::Type>(opcode), instr);
 +    }
 +}
 +
 +void QV4CompilerPrivate::visitCall(IR::Call *call)
 +{
 +    if (IR::Name *name = call->base->asName()) {
 +        IR::Expr *arg = call->onlyArgument();
 +        if (arg != 0 && arg->type == IR::RealType) {
 +            traceExpression(arg, currentReg);
 +
 +            switch (name->builtin) {
 +            case IR::NoBuiltinSymbol:
 +                break;
 +
 +            case IR::MathSinBultinFunction: {
 +                Instr::MathSinReal i;
 +                i.output = i.src = currentReg;
 +                gen(i);
 +                } return;
 +
 +            case IR::MathCosBultinFunction: {
 +                Instr::MathCosReal i;
 +                i.output = i.src = currentReg;
 +                gen(i);
 +                } return;
 +
 +            case IR::MathRoundBultinFunction: {
 +                Instr::MathRoundReal i;
 +                i.output = i.src = currentReg;
 +                gen(i);
 +                } return;
 +
 +            case IR::MathFloorBultinFunction: {
 +                Instr::MathFloorReal i;
 +                i.output = i.src = currentReg;
 +                gen(i);
 +                } return;
 +
 +            case IR::MathPIBuiltinConstant:
 +                break;
 +            } // switch
 +        }
 +    }
 +
 +    if (qmlVerboseCompiler())
 +        qWarning() << "TODO:" << Q_FUNC_INFO << __LINE__;
 +    discard();
 +}
 +
 +
 +//
 +// statements
 +//
 +void QV4CompilerPrivate::visitExp(IR::Exp *s)
 +{
 +    traceExpression(s->expr, currentReg);
 +}
 +
 +void QV4CompilerPrivate::visitMove(IR::Move *s)
 +{
 +    IR::Temp *target = s->target->asTemp();
 +    Q_ASSERT(target != 0);
 +
 +    quint8 dest = target->index;
 +
 +    if (target->type != s->source->type) {
 +        quint8 src = dest;
 +
 +        if (IR::Temp *t = s->source->asTemp()) 
 +            src = t->index;
 +        else
 +            traceExpression(s->source, dest);
 +
 +        V4Instr::Type opcode = V4Instr::Noop;
 +        IR::Type targetTy = s->target->type;
 +        IR::Type sourceTy = s->source->type;
 +
 +        if (sourceTy == IR::UrlType) {
 +            switch (targetTy) {
 +            case IR::BoolType:
 +            case IR::StringType:
 +                // nothing to do. V4 will generate optimized
 +                // url-to-xxx conversions.
 +                break;
 +            default: {
 +                // generate a UrlToString conversion and fix
 +                // the type of the source expression.
 +                V4Instr conv;
 +                conv.unaryop.output = V4Instr::ConvertUrlToString;
 +                conv.unaryop.src = src;
 +                gen(opcode, conv);
 +
 +                sourceTy = IR::StringType;
 +                break;
 +            }
 +            } // switch
 +        }
 +
 +        if (targetTy == IR::BoolType) {
 +            switch (sourceTy) {
 +            case IR::IntType: opcode = V4Instr::ConvertIntToBool; break;
 +            case IR::RealType: opcode = V4Instr::ConvertRealToBool; break;
 +            case IR::StringType: opcode = V4Instr::ConvertStringToBool; break;
 +            case IR::UrlType: opcode = V4Instr::ConvertUrlToBool; break;
++            case IR::ColorType: opcode = V4Instr::ConvertColorToBool; break;
 +            default: break;
 +            } // switch
 +        } else if (targetTy == IR::IntType) {
 +            switch (sourceTy) {
 +            case IR::BoolType: opcode = V4Instr::ConvertBoolToInt; break;
 +            case IR::RealType: {
 +                if (s->isMoveForReturn)
 +                    opcode = V4Instr::MathRoundReal;
 +                else
 +                    opcode = V4Instr::ConvertRealToInt;
 +                break;
 +            }
 +            case IR::StringType: opcode = V4Instr::ConvertStringToInt; break;
 +            default: break;
 +            } // switch
 +        } else if (targetTy == IR::RealType) {
 +            switch (sourceTy) {
 +            case IR::BoolType: opcode = V4Instr::ConvertBoolToReal; break;
 +            case IR::IntType: opcode = V4Instr::ConvertIntToReal; break;
 +            case IR::StringType: opcode = V4Instr::ConvertStringToReal; break;
 +            default: break;
 +            } // switch
 +        } else if (targetTy == IR::StringType) {
 +            switch (sourceTy) {
 +            case IR::BoolType: opcode = V4Instr::ConvertBoolToString; break;
 +            case IR::IntType:  opcode = V4Instr::ConvertIntToString; break;
 +            case IR::RealType: opcode = V4Instr::ConvertRealToString; break;
 +            case IR::UrlType: opcode = V4Instr::ConvertUrlToString; break;
++            case IR::ColorType: opcode = V4Instr::ConvertColorToString; break;
 +            default: break;
 +            } // switch
 +        } else if (targetTy == IR::UrlType) {
 +            V4Instr convToString;
 +            convToString.unaryop.output = dest;
 +            convToString.unaryop.src = src;
 +
 +            // try to convert the source expression to a string.
 +            switch (sourceTy) {
 +            case IR::BoolType: gen(V4Instr::ConvertBoolToString, convToString); sourceTy = IR::StringType; break;
 +            case IR::IntType:  gen(V4Instr::ConvertIntToString,  convToString); sourceTy = IR::StringType; break;
 +            case IR::RealType: gen(V4Instr::ConvertRealToString, convToString); sourceTy = IR::StringType; break;
++            case IR::ColorType: gen(V4Instr::ConvertColorToString, convToString); sourceTy = IR::StringType; break;
 +            default: break;
 +            } // switch
 +
 +            if (sourceTy == IR::StringType)
 +                opcode = V4Instr::ConvertStringToUrl;
++        } else if (targetTy == IR::ColorType) {
++            switch (sourceTy) {
++            case IR::StringType: opcode = V4Instr::ConvertStringToColor; break;
++            default: break;
++            } // switch
 +        }
 +        if (opcode != V4Instr::Noop) {
 +            V4Instr conv;
 +            conv.unaryop.output = dest;
 +            conv.unaryop.src = src;
 +            gen(opcode, conv);
 +
 +            if (s->isMoveForReturn && opcode == V4Instr::ConvertStringToUrl) {
 +                V4Instr resolveUrl;
 +                resolveUrl.unaryop.output = dest;
 +                resolveUrl.unaryop.src = dest;
 +                gen(V4Instr::ResolveUrl, resolveUrl);
 +            }
 +        } else {
 +            discard();
 +        }
 +    } else {
 +        traceExpression(s->source, dest);
 +    }
 +}
 +
 +void QV4CompilerPrivate::visitJump(IR::Jump *s)
 +{
 +    patches.append(Patch(s->target, bytecode.size()));
 +
 +    Instr::Branch i;
 +    i.offset = 0; // ### backpatch
 +    gen(i);
 +}
 +
 +void QV4CompilerPrivate::visitCJump(IR::CJump *s)
 +{
 +    traceExpression(s->cond, currentReg);
 +
 +    patches.append(Patch(s->iftrue, bytecode.size()));
 +
 +    Instr::BranchTrue i;
 +    i.reg = currentReg;
 +    i.offset = 0; // ### backpatch
 +    gen(i);
 +}
 +
 +void QV4CompilerPrivate::visitRet(IR::Ret *s)
 +{
 +    Q_ASSERT(s->expr != 0);
 +
 +    int storeReg = currentReg;
 +
 +    if (IR::Temp *temp = s->expr->asTemp()) {
 +        storeReg = temp->index;
 +    } else {
 +        traceExpression(s->expr, storeReg);
 +    }
 +
 +    if (qmlBindingsTest) {
 +        Instr::TestV4Store test;
 +        test.reg = storeReg;
 +        switch (s->type) {
 +        case IR::StringType:
 +            test.regType = QMetaType::QString;
 +            break;
 +        case IR::UrlType:
 +            test.regType = QMetaType::QUrl;
 +            break;
++        case IR::ColorType:
++            test.regType = QMetaType::QColor;
++            break;
 +        case IR::SGAnchorLineType:
 +            test.regType = QQmlMetaType::QQuickAnchorLineMetaTypeId();
 +            break;
 +        case IR::ObjectType:
 +            test.regType = QMetaType::QObjectStar;
 +            break;
 +        case IR::BoolType:
 +            test.regType = QMetaType::Bool;
 +            break;
 +        case IR::IntType:
 +            test.regType = QMetaType::Int;
 +            break;
 +        case IR::RealType:
 +            test.regType = QMetaType::QReal;
 +            break;
 +        default:
 +            discard();
 +            return;
 +        }
 +        gen(test);
 +    }
 +
 +    Instr::Store store;
 +    store.output = 0;
 +    store.index = expression->property->index;
 +    store.reg = storeReg;
 +    store.exceptionId = exceptionId(s->line, s->column);
 +    gen(store);
 +}
 +
 +void QV4Compiler::dump(const QByteArray &programData)
 +{
 +    const QV4Program *program = (const QV4Program *)programData.constData();
 +
 +    qWarning() << "Program.bindings:" << program->bindings;
 +    qWarning() << "Program.dataLength:" << program->dataLength;
 +    qWarning() << "Program.subscriptions:" << program->subscriptions;
 +    qWarning() << "Program.indentifiers:" << program->identifiers;
 +
 +    const int programSize = program->instructionCount;
 +    const char *start = program->instructions();
 +    const char *end = start + programSize;
 +    Bytecode bc;
 +    bc.dump(start, end);
 +}
 +
 +/*!
 +Clear the state associated with attempting to compile a specific binding.
 +This does not clear the global "committed binding" states.
 +*/
 +void QV4CompilerPrivate::resetInstanceState()
 +{
 +    data = committed.data;
 +    exceptions = committed.exceptions;
 +    usedSubscriptionIds.clear();
 +    subscriptionIds = committed.subscriptionIds;
 +    registeredStrings = committed.registeredStrings;
 +    bytecode.clear();
 +    patches.clear();
 +    pool.clear();
 +    currentReg = 0;
 +}
 +
 +/*!
 +Mark the last compile as successful, and add it to the "committed data"
 +section.
 +
 +Returns the index for the committed binding.
 +*/
 +int QV4CompilerPrivate::commitCompile()
 +{
 +    int rv = committed.count();
 +    committed.offsets << committed.bytecode.count();
 +    committed.dependencies << usedSubscriptionIds;
 +    committed.bytecode.append(bytecode.constData(), bytecode.size());
 +    committed.data = data;
 +    committed.exceptions = exceptions;
 +    committed.subscriptionIds = subscriptionIds;
 +    committed.registeredStrings = registeredStrings;
 +    return rv;
 +}
 +
 +bool QV4CompilerPrivate::compile(QQmlJS::AST::Node *node)
 +{
 +    resetInstanceState();
 +
 +    if (expression->property->type == -1)
 +        return false;
 +
 +    AST::SourceLocation location;
 +    if (AST::ExpressionNode *astExpression = node->expressionCast()) {
 +        location = astExpression->firstSourceLocation();
 +    } else if (AST::Statement *astStatement = node->statementCast()) {
 +        if (AST::Block *block = AST::cast<AST::Block *>(astStatement))
 +            location = block->lbraceToken;
 +        else if (AST::IfStatement *ifStmt = AST::cast<AST::IfStatement *>(astStatement))
 +            location = ifStmt->ifToken;
 +        else
 +            return false;
 +    } else {
 +        return false;
 +    }
 +
 +    IR::Function thisFunction(&pool), *function = &thisFunction;
 +
 +    QV4IRBuilder irBuilder(expression, engine);
 +    if (!irBuilder(function, node))
 +        return false;
 +
 +    bool discarded = false;
 +    qSwap(_discarded, discarded);
 +    qSwap(_function, function);
 +    trace(location.startLine, location.startColumn);
 +    qSwap(_function, function);
 +    qSwap(_discarded, discarded);
 +
 +    if (qmlVerboseCompiler()) {
 +        QTextStream qerr(stderr, QIODevice::WriteOnly);
 +        if (discarded)
 +            qerr << "======== TODO ====== " << endl;
 +        else 
 +            qerr << "==================== " << endl;
 +        qerr << "\tline: " << location.startLine
 +             << "\tcolumn: " << location.startColumn
 +             << endl;
 +        foreach (IR::BasicBlock *bb, function->basicBlocks)
 +            bb->dump(qerr);
 +        qerr << endl;
 +    }
 +
++    if (discarded || subscriptionIds.count() > 0xFFFF || registeredStrings.count() > 0xFFFF || registerCount > 31)
 +        return false;
 +
 +    return true;
 +}
 +
 +// Returns a reg
 +int QV4CompilerPrivate::registerLiteralString(quint8 reg, const QStringRef &str)
 +{
 +    // ### string cleanup
 +
 +    QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar));
 +    int offset = data.count();
 +    data += strdata;
 +
 +    Instr::LoadString string;
 +    string.reg = reg;
 +    string.offset = offset;
 +    string.length = str.length();
 +    gen(string);
 +
 +    return reg;
 +}
 +
 +// Returns an identifier offset
 +int QV4CompilerPrivate::registerString(const QString &string)
 +{
 +    Q_ASSERT(!string.isEmpty());
 +
 +    QPair<int, int> *iter = registeredStrings.value(string);
 +
 +    if (!iter) {
 +        quint32 len = string.length();
 +        QByteArray lendata((const char *)&len, sizeof(quint32));
 +        QByteArray strdata((const char *)string.constData(), string.length() * sizeof(QChar));
 +        strdata.prepend(lendata);
 +        int rv = data.count();
 +        data += strdata;
 +
 +        iter = &registeredStrings[string];
 +        *iter = qMakePair(registeredStrings.count(), rv);
 +    } 
 +
 +    Instr::InitString reg;
 +    reg.offset = iter->first;
 +    reg.dataIdx = iter->second;
 +    gen(reg);
 +    return reg.offset;
 +}
 +
 +/*!
 +Returns true if the current expression has not already subscribed to \a sub in currentBlockMask.
 +*/
 +bool QV4CompilerPrivate::blockNeedsSubscription(const QStringList &sub)
 +{
 +    QString str = sub.join(QLatin1String("."));
 +
 +    int *iter = subscriptionIds.value(str);
 +    if (!iter)
 +        return true;
 +
 +    quint32 *uiter = usedSubscriptionIds.value(*iter);
 +    if (!uiter)
 +        return true;
 +    else
 +        return !(*uiter & currentBlockMask);
 +}
 +
 +int QV4CompilerPrivate::subscriptionIndex(const QStringList &sub)
 +{
 +    QString str = sub.join(QLatin1String("."));
 +    int *iter = subscriptionIds.value(str);
 +    if (!iter) {
 +        int count = subscriptionIds.count();
 +        iter = &subscriptionIds[str];
 +        *iter = count;
 +    }
 +    quint32 &u = usedSubscriptionIds[*iter];
 +    if (!(u & currentBlockMask)) {
 +        u |= currentBlockMask;
 +        usedSubscriptionIdsChanged = true;
 +    }
 +    return *iter;
 +}
 +
 +quint32 QV4CompilerPrivate::subscriptionBlockMask(const QStringList &sub)
 +{
 +    QString str = sub.join(QLatin1String("."));
 +
 +    int *iter = subscriptionIds.value(str);
 +    Q_ASSERT(iter != 0);
 +
 +    quint32 *uiter = usedSubscriptionIds.value(*iter);
 +    Q_ASSERT(uiter != 0);
 +
 +    return *uiter;
 +}
 +
 +quint8 QV4CompilerPrivate::exceptionId(quint32 line, quint32 column)
 +{
 +    quint8 rv = 0xFF;
 +    if (exceptions.count() < 0xFF) {
 +        rv = (quint8)exceptions.count();
 +        quint64 e = line;
 +        e <<= 32;
 +        e |= column;
 +        exceptions.append(e);
 +    }
 +    return rv;
 +}
 +
 +quint8 QV4CompilerPrivate::exceptionId(QQmlJS::AST::ExpressionNode *n)
 +{
 +    quint8 rv = 0xFF;
 +    if (n && exceptions.count() < 0xFF) {
 +        QQmlJS::AST::SourceLocation l = n->firstSourceLocation();
 +        rv = exceptionId(l.startLine, l.startColumn);
 +    }
 +    return rv;
 +}
 +
 +QV4Compiler::QV4Compiler()
 +: d(new QV4CompilerPrivate)
 +{
 +    qmlBindingsTest |= qmlBindingsTestEnv();
 +}
 +
 +QV4Compiler::~QV4Compiler()
 +{
 +    delete d; d = 0;
 +}
 +
 +/* 
 +Returns true if any bindings were compiled.
 +*/
 +bool QV4Compiler::isValid() const
 +{
 +    return !d->committed.bytecode.isEmpty();
 +}
 +
 +/* 
 +-1 on failure, otherwise the binding index to use.
 +*/
 +int QV4Compiler::compile(const Expression &expression, QQmlEnginePrivate *engine)
 +{
 +    if (!expression.expression.asAST()) return false;
 +
 +    if (!qmlExperimental() && expression.property->isValueTypeSubProperty)
 +        return -1;
 +
 +    if (qmlDisableOptimizer() || !qmlEnableV4)
 +        return -1;
 +
 +    d->expression = &expression;
 +    d->engine = engine;
 +
 +    if (d->compile(expression.expression.asAST())) {
 +        return d->commitCompile();
 +    } else {
 +        return -1;
 +    }
 +}
 +
 +QByteArray QV4CompilerPrivate::buildSignalTable() const
 +{
 +    QHash<int, QList<QPair<int, quint32> > > table;
 +
 +    for (int ii = 0; ii < committed.count(); ++ii) {
 +        const QQmlAssociationList<int, quint32> &deps = committed.dependencies.at(ii);
 +        for (QQmlAssociationList<int, quint32>::const_iterator iter = deps.begin(); iter != deps.end(); ++iter)
 +            table[iter->first].append(qMakePair(ii, iter->second));
 +    }
 +
 +    QVector<quint32> header;
 +    QVector<quint32> data;
 +    for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) {
 +        header.append(committed.subscriptionIds.count() + data.count());
 +        const QList<QPair<int, quint32> > &bindings = table[ii];
 +        data.append(bindings.count());
 +        for (int jj = 0; jj < bindings.count(); ++jj) {
 +            data.append(bindings.at(jj).first);
 +            data.append(bindings.at(jj).second);
 +        }
 +    }
 +    header << data;
 +
 +    return QByteArray((const char *)header.constData(), header.count() * sizeof(quint32));
 +}
 +
 +QByteArray QV4CompilerPrivate::buildExceptionData() const
 +{
 +    QByteArray rv;
 +    rv.resize(committed.exceptions.count() * sizeof(quint64));
 +    ::memcpy(rv.data(), committed.exceptions.constData(), rv.size());
 +    return rv;
 +}
 +
 +/* 
 +Returns the compiled program.
 +*/
 +QByteArray QV4Compiler::program() const
 +{
 +    QByteArray programData;
 +
 +    if (isValid()) {
 +        QV4Program prog;
 +        prog.bindings = d->committed.count();
 +
 +        Bytecode bc;
 +        QV4CompilerPrivate::Instr::Jump jump;
 +        jump.reg = -1;
 +
 +        for (int ii = 0; ii < d->committed.count(); ++ii) {
 +            jump.count = d->committed.count() - ii - 1;
 +            jump.count*= V4InstrMeta<V4Instr::Jump>::Size;
 +            jump.count+= d->committed.offsets.at(ii);
 +            bc.append(jump);
 +        }
 +
 +
 +        QByteArray bytecode;
 +        bytecode.reserve(bc.size() + d->committed.bytecode.size());
 +        bytecode.append(bc.constData(), bc.size());
 +        bytecode.append(d->committed.bytecode.constData(), d->committed.bytecode.size());
 +
 +        QByteArray data = d->committed.data;
 +        while (data.count() % 4) data.append('\0');
 +        prog.signalTableOffset = data.count();
 +        data += d->buildSignalTable();
 +        while (data.count() % 4) data.append('\0');
 +        prog.exceptionDataOffset = data.count();
 +        data += d->buildExceptionData();
 +
 +        prog.dataLength = 4 * ((data.size() + 3) / 4);
 +        prog.subscriptions = d->committed.subscriptionIds.count();
 +        prog.identifiers = d->committed.registeredStrings.count();
 +        prog.instructionCount = bytecode.count();
 +        int size = sizeof(QV4Program) + bytecode.count();
 +        size += prog.dataLength;
 +
 +        programData.resize(size);
 +        memcpy(programData.data(), &prog, sizeof(QV4Program));
 +        if (prog.dataLength)
 +            memcpy((char *)((QV4Program *)programData.data())->data(), data.constData(), 
 +                   data.size());
 +        memcpy((char *)((QV4Program *)programData.data())->instructions(), bytecode.constData(),
 +               bytecode.count());
 +    } 
 +
 +    if (bindingsDump()) {
 +        qWarning().nospace() << "Subscription slots:";
 +
 +        for (QQmlAssociationList<QString, int>::ConstIterator iter = d->committed.subscriptionIds.begin();
 +                iter != d->committed.subscriptionIds.end();
 +                ++iter) {
 +            qWarning().nospace() << "    " << iter->first << "\t-> " << iter->second;
 +        }
 +
 +        QV4Compiler::dump(programData);
 +    }
 +
 +    return programData;
 +}
 +
 +void QV4Compiler::enableBindingsTest(bool e)
 +{
 +    if (e)
 +        qmlBindingsTest = true;
 +    else 
 +        qmlBindingsTest = qmlBindingsTestEnv();
 +}
 +
 +void QV4Compiler::enableV4(bool e)
 +{
 +    qmlEnableV4 = e;
 +}
 +
 +QT_END_NAMESPACE
index 4b74a1d,0000000..a9209d9
mode 100644,000000..100644
--- /dev/null
@@@ -1,245 -1,0 +1,246 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QV4COMPILER_P_P_H
 +#define QV4COMPILER_P_P_H
 +
 +//
 +//  W A R N I N G
 +//  -------------
 +//
 +// This file is not part of the Qt API.  It exists purely as an
 +// implementation detail.  This header file may change from version to
 +// version without notice, or even be removed.
 +//
 +// We mean it.
 +//
 +
 +#include "qv4instruction_p.h"
 +#include "qv4ir_p.h"
 +#include <private/qqmlscript_p.h>
 +#include <private/qqmlimport_p.h>
 +#include <private/qqmlengine_p.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +template <typename _Key, typename _Value>
 +class QQmlAssociationList
 +{
 +public:
 +    typedef QVarLengthArray<QPair<_Key, _Value>, 8> Container;
 +    typedef typename Container::const_iterator const_iterator;
 +    typedef typename Container::const_iterator ConstIterator;
 +
 +    const_iterator begin() const { return _container.begin(); }
 +    const_iterator end() const { return _container.end(); }
 +    int count() const { return _container.count(); }
 +    void clear() { _container.clear(); }
 +
 +    _Value *value(const _Key &key) {
 +        for (int i = 0; i < _container.size(); ++i) {
 +            QPair<_Key, _Value> &p = _container[i];
 +            if (p.first == key)
 +                return &p.second;
 +        }
 +        return 0;
 +    }
 +
 +    _Value &operator[](const _Key &key) {
 +        for (int i = 0; i < _container.size(); ++i) {
 +            QPair<_Key, _Value> &p = _container[i];
 +            if (p.first == key)
 +                return p.second;
 +        }
 +        int index = _container.size();
 +        _container.append(qMakePair(key, _Value()));
 +        return _container[index].second;
 +    }
 +
 +    void insert(const _Key &key, _Value &value) {
 +        for (int i = 0; i < _container.size(); ++i) {
 +            QPair<_Key, _Value> &p = _container[i];
 +            if (p.first == key) {
 +                p.second = value;
 +                return;
 +            }
 +        }
 +        _container.append(qMakePair(key, value));
 +    }
 +
 +private:
 +    Container _container;
 +};
 +
 +class QV4CompilerPrivate: protected QQmlJS::IR::ExprVisitor, 
 +                                     protected QQmlJS::IR::StmtVisitor
 +{
 +public:
 +    QV4CompilerPrivate();
 +
 +    void resetInstanceState();
 +    int commitCompile();
 +
 +    const QV4Compiler::Expression *expression;
 +    QQmlEnginePrivate *engine;
 +
 +    QString contextName() const { return QLatin1String("$$$SCOPE_") + QString::number((quintptr)expression->context, 16); }
 +
 +    bool compile(QQmlJS::AST::Node *);
 +
 +    int registerLiteralString(quint8 reg, const QStringRef &);
 +    int registerString(const QString &);
 +    QQmlAssociationList<QString, QPair<int, int> > registeredStrings;
 +    QByteArray data;
 +
 +    bool blockNeedsSubscription(const QStringList &);
 +    int subscriptionIndex(const QStringList &);
 +    quint32 subscriptionBlockMask(const QStringList &);
 +
 +    quint8 exceptionId(quint32 line, quint32 column);
 +    quint8 exceptionId(QQmlJS::AST::ExpressionNode *);
 +    QVector<quint64> exceptions;
 +
 +    QQmlAssociationList<int, quint32> usedSubscriptionIds;
 +
 +    QQmlAssociationList<QString, int> subscriptionIds;
 +    QQmlJS::Bytecode bytecode;
 +
 +    // back patching
 +    struct Patch {
 +        QQmlJS::IR::BasicBlock *block; // the basic block
 +        int offset; // the index of the instruction to patch
 +        Patch(QQmlJS::IR::BasicBlock *block = 0, int index = -1)
 +            : block(block), offset(index) {}
 +    };
 +    QVector<Patch> patches;
 +    QQmlPool pool;
 +
 +    // Committed binding data
 +    struct {
 +        QList<int> offsets;
 +        QList<QQmlAssociationList<int, quint32> > dependencies;
 +
 +        //QQmlJS::Bytecode bytecode;
 +        QByteArray bytecode;
 +        QByteArray data;
 +        QQmlAssociationList<QString, int> subscriptionIds;
 +        QVector<quint64> exceptions;
 +
 +        QQmlAssociationList<QString, QPair<int, int> > registeredStrings;
 +
 +        int count() const { return offsets.count(); }
 +    } committed;
 +
 +    QByteArray buildSignalTable() const;
 +    QByteArray buildExceptionData() const;
 +
 +    void convertToReal(QQmlJS::IR::Expr *expr, int reg);    
 +    void convertToInt(QQmlJS::IR::Expr *expr, int reg);
 +    void convertToBool(QQmlJS::IR::Expr *expr, int reg);
 +    quint8 instructionOpcode(QQmlJS::IR::Binop *e);
 +
 +    struct Instr {
 +#define QML_V4_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlJS::V4InstrData<QQmlJS::V4Instr::I> I;
 +    FOR_EACH_V4_INSTR(QML_V4_INSTR_DATA_TYPEDEF)
 +#undef QML_v4_INSTR_DATA_TYPEDEF
 +    private:
 +        Instr();
 +    };
 +
 +protected:
 +    //
 +    // tracing
 +    //
 +    void trace(int line, int column);
 +    void trace(QVector<QQmlJS::IR::BasicBlock *> *blocks);
 +    void traceExpression(QQmlJS::IR::Expr *e, quint8 r);
 +
 +    template <int Instr>
 +    inline void gen(const QQmlJS::V4InstrData<Instr> &i)
 +    { bytecode.append(i); }
 +    inline void gen(QQmlJS::V4Instr::Type type, QQmlJS::V4Instr &instr)
 +    { bytecode.append(type, instr); }
 +
 +    inline QQmlJS::V4Instr::Type instructionType(const QQmlJS::V4Instr *i) const
 +    { return bytecode.instructionType(i); }
 +
 +    //
 +    // expressions
 +    //
 +    virtual void visitConst(QQmlJS::IR::Const *e);
 +    virtual void visitString(QQmlJS::IR::String *e);
 +    virtual void visitName(QQmlJS::IR::Name *e);
 +    virtual void visitTemp(QQmlJS::IR::Temp *e);
 +    virtual void visitUnop(QQmlJS::IR::Unop *e);
 +    virtual void visitBinop(QQmlJS::IR::Binop *e);
 +    virtual void visitCall(QQmlJS::IR::Call *e);
 +
 +    //
 +    // statements
 +    //
 +    virtual void visitExp(QQmlJS::IR::Exp *s);
 +    virtual void visitMove(QQmlJS::IR::Move *s);
 +    virtual void visitJump(QQmlJS::IR::Jump *s);
 +    virtual void visitCJump(QQmlJS::IR::CJump *s);
 +    virtual void visitRet(QQmlJS::IR::Ret *s);
 +
 +private:
 +    QStringList _subscribeName;
 +    QQmlJS::IR::Function *_function;
 +    QQmlJS::IR::BasicBlock *_block;
 +    void discard() { _discarded = true; }
 +    bool _discarded;
 +    quint8 currentReg;
++    quint8 registerCount;
 +
 +    bool usedSubscriptionIdsChanged;
 +    quint32 currentBlockMask;
 +};
 +
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QV4COMPILER_P_P_H
 +
index 08b2570,0000000..efbd2b2
mode 100644,000000..100644
--- /dev/null
@@@ -1,412 -1,0 +1,421 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qv4instruction_p.h"
 +#include "qv4bindings_p.h"
 +
 +#include <QtCore/qdebug.h>
 +#include <private/qqmlglobal_p.h>
 +
 +// Define this to do a test dump of all the instructions at startup.  This is 
 +// helpful to test that each instruction's Instr::dump() case uses the correct
 +// number of tabs etc and otherwise looks correct.
 +// #define DEBUG_INSTR_DUMP
 +
 +QT_BEGIN_NAMESPACE
 +
 +namespace QQmlJS {
 +
 +#ifdef DEBUG_INSTR_DUMP
 +static struct DumpInstrAtStartup {
 +    DumpInstrAtStartup() {
 +        Bytecode bc;
 +#define DUMP_INSTR_AT_STARTUP(I, FMT) { V4InstrData<V4Instr::I> i; bc.append(i); }
 +        FOR_EACH_V4_INSTR(DUMP_INSTR_AT_STARTUP);
 +#undef DUMP_INSTR_AT_STARTUP
 +        const char *start = bc.constData();
 +        const char *end = start + bc.size();
 +        bc.dump(start, end);
 +    }
 +} dump_instr_at_startup;
 +#endif
 +
 +int V4Instr::size(Type type)
 +{
 +#define V4_RETURN_INSTR_SIZE(I, FMT) case I: return QML_V4_INSTR_SIZE(I, FMT);
 +    switch (type) {
 +    FOR_EACH_V4_INSTR(V4_RETURN_INSTR_SIZE)
 +    }
 +#undef V4_RETURN_INSTR_SIZE
 +    return 0;
 +}
 +
 +void Bytecode::dump(const V4Instr *i, int address) const
 +{
 +    QByteArray leading;
 +    if (address != -1) {
 +        leading = QByteArray::number(address);
 +        leading.prepend(QByteArray(8 - leading.count(), ' '));
 +        leading.append("\t");
 +    }
 +
 +#define INSTR_DUMP qWarning().nospace() << leading.constData() 
 +
 +    switch (instructionType(i)) {
 +    case V4Instr::Noop:
 +        INSTR_DUMP << "\t" << "Noop";
 +        break;
 +    case V4Instr::BindingId:
 +        INSTR_DUMP << i->id.line << ":" << i->id.column << ":";
 +        break;
 +    case V4Instr::Subscribe:
 +        INSTR_DUMP << "\t" << "Subscribe" << "\t\t" << "Object_Reg(" << i->subscribeop.reg << ") Notify_Signal(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")";
 +        break;
 +    case V4Instr::SubscribeId:
 +        INSTR_DUMP << "\t" << "SubscribeId" << "\t\t" << "Id_Offset(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")";
 +        break;
 +    case V4Instr::FetchAndSubscribe:
 +        INSTR_DUMP << "\t" << "FetchAndSubscribe" << "\t" << "Object_Reg(" << i->fetchAndSubscribe.reg << ") Fast_Accessor(" << i->fetchAndSubscribe.property.accessors << ") -> Output_Reg(" << i->fetchAndSubscribe.reg << ") Subscription_Slot(" <<  i->fetchAndSubscribe.subscription << ")";
 +        break;
 +    case V4Instr::LoadId:
 +        INSTR_DUMP << "\t" << "LoadId" << "\t\t\t" << "Id_Offset(" << i->load.index << ") -> Output_Reg(" << i->load.reg << ")";
 +        break;
 +    case V4Instr::LoadScope:
 +        INSTR_DUMP << "\t" << "LoadScope" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")";
 +        break;
 +    case V4Instr::LoadRoot:
 +        INSTR_DUMP << "\t" << "LoadRoot" << "\t\t" << "-> Output_Reg(" << i->load.reg << ")";
 +        break;
 +    case V4Instr::LoadAttached:
 +        INSTR_DUMP << "\t" << "LoadAttached" << "\t\t" << "Object_Reg(" << i->attached.reg << ") Attached_Index(" << i->attached.id << ") -> Output_Reg(" << i->attached.output << ")";
 +        break;
 +    case V4Instr::UnaryNot:
 +        INSTR_DUMP << "\t" << "UnaryNot" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::UnaryMinusReal:
 +        INSTR_DUMP << "\t" << "UnaryMinusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::UnaryMinusInt:
 +        INSTR_DUMP << "\t" << "UnaryMinusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::UnaryPlusReal:
 +        INSTR_DUMP << "\t" << "UnaryPlusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::UnaryPlusInt:
 +        INSTR_DUMP << "\t" << "UnaryPlusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertBoolToInt:
 +        INSTR_DUMP << "\t" << "ConvertBoolToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertBoolToReal:
 +        INSTR_DUMP << "\t" << "ConvertBoolToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertBoolToString:
 +        INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertIntToBool:
 +        INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertIntToReal:
 +        INSTR_DUMP << "\t" << "ConvertIntToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertIntToString:
 +        INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertRealToBool:
 +        INSTR_DUMP << "\t" << "ConvertRealToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertRealToInt:
 +        INSTR_DUMP << "\t" << "ConvertRealToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertRealToString:
 +        INSTR_DUMP << "\t" << "ConvertRealToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertStringToBool:
 +        INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertStringToInt:
 +        INSTR_DUMP << "\t" << "ConvertStringToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertStringToReal:
 +        INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertStringToUrl:
 +        INSTR_DUMP << "\t" << "ConvertStringToUrl" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
++    case V4Instr::ConvertStringToColor:
++        INSTR_DUMP << "\t" << "ConvertStringToColor" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
++        break;
 +    case V4Instr::ConvertUrlToBool:
 +        INSTR_DUMP << "\t" << "ConvertUrlToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::ConvertUrlToString:
 +        INSTR_DUMP << "\t" << "ConvertUrlToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
++    case V4Instr::ConvertColorToBool:
++        INSTR_DUMP << "\t" << "ConvertColorToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
++        break;
++    case V4Instr::ConvertColorToString:
++        INSTR_DUMP << "\t" << "ConvertColorToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
++        break;
 +    case V4Instr::ResolveUrl:
 +        INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::MathSinReal:
 +        INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::MathCosReal:
 +        INSTR_DUMP << "\t" << "MathCosReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::MathRoundReal:
 +        INSTR_DUMP << "\t" << "MathRoundReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::MathFloorReal:
 +        INSTR_DUMP << "\t" << "MathFloorReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::MathPIReal:
 +        INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
 +        break;
 +    case V4Instr::LoadReal:
 +        INSTR_DUMP << "\t" << "LoadReal" << "\t\t" << "Constant(" << i->real_value.value << ") -> Output_Reg(" << i->real_value.reg << ")";
 +        break;
 +    case V4Instr::LoadInt:
 +        INSTR_DUMP << "\t" << "LoadInt" << "\t\t\t" << "Constant(" << i->int_value.value << ") -> Output_Reg(" << i->int_value.reg << ")";
 +        break;
 +    case V4Instr::LoadBool:
 +        INSTR_DUMP << "\t" << "LoadBool" << "\t\t" << "Constant(" << i->bool_value.value << ") -> Output_Reg(" << i->bool_value.reg << ")";
 +        break;
 +    case V4Instr::LoadString:
 +        INSTR_DUMP << "\t" << "LoadString" << "\t\t" << "String_DataIndex(" << i->string_value.offset << ") String_Length(" << i->string_value.length << ") -> Output_Register(" << i->string_value.reg << ")";
 +        break;
 +    case V4Instr::EnableV4Test:
 +        INSTR_DUMP << "\t" << "EnableV4Test" << "\t\t" << "String_DataIndex(" << i->string_value.offset << ") String_Length(" << i->string_value.length << ")";
 +        break;
 +    case V4Instr::TestV4Store:
 +        INSTR_DUMP << "\t" << "TestV4Store" << "\t\t" << "Input_Reg(" << i->storetest.reg << ") Reg_Type(" << i->storetest.regType << ")";
 +        break;
 +    case V4Instr::BitAndInt:
 +        INSTR_DUMP << "\t" << "BitAndInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::BitOrInt:
 +        INSTR_DUMP << "\t" << "BitOrInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::BitXorInt:
 +        INSTR_DUMP << "\t" << "BitXorInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::AddReal:
 +        INSTR_DUMP << "\t" << "AddReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::AddString:
 +        INSTR_DUMP << "\t" << "AddString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::SubReal:
 +        INSTR_DUMP << "\t" << "SubReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::MulReal:
 +        INSTR_DUMP << "\t" << "MulReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::DivReal:
 +        INSTR_DUMP << "\t" << "DivReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::ModReal:
 +        INSTR_DUMP << "\t" << "ModReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::LShiftInt:
 +        INSTR_DUMP << "\t" << "LShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::RShiftInt:
 +        INSTR_DUMP << "\t" << "RShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::URShiftInt:
 +        INSTR_DUMP << "\t" << "URShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::GtReal:
 +        INSTR_DUMP << "\t" << "GtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::LtReal:
 +        INSTR_DUMP << "\t" << "LtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::GeReal:
 +        INSTR_DUMP << "\t" << "GeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::LeReal:
 +        INSTR_DUMP << "\t" << "LeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::EqualReal:
 +        INSTR_DUMP << "\t" << "EqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::NotEqualReal:
 +        INSTR_DUMP << "\t" << "NotEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::StrictEqualReal:
 +        INSTR_DUMP << "\t" << "StrictEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::StrictNotEqualReal:
 +        INSTR_DUMP << "\t" << "StrictNotEqualReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::GtString:
 +        INSTR_DUMP << "\t" << "GtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::LtString:
 +        INSTR_DUMP << "\t" << "LtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::GeString:
 +        INSTR_DUMP << "\t" << "GeString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::LeString:
 +        INSTR_DUMP << "\t" << "LeString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::EqualString:
 +        INSTR_DUMP << "\t" << "EqualString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::NotEqualString:
 +        INSTR_DUMP << "\t" << "NotEqualString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::StrictEqualString:
 +        INSTR_DUMP << "\t" << "StrictEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::StrictNotEqualString:
 +        INSTR_DUMP << "\t" << "StrictNotEqualString" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
 +        break;
 +    case V4Instr::NewString:
 +        INSTR_DUMP << "\t" << "NewString" << "\t\t" << "Register(" << i->construct.reg << ")";
 +        break;
 +    case V4Instr::NewUrl:
 +        INSTR_DUMP << "\t" << "NewUrl" << "\t\t\t" << "Register(" << i->construct.reg << ")";
 +        break;
 +    case V4Instr::CleanupRegister:
 +        INSTR_DUMP << "\t" << "CleanupRegister" << "\t\t" << "Register(" << i->cleanup.reg << ")";
 +        break;
 +    case V4Instr::Fetch:
 +        INSTR_DUMP << "\t" << "Fetch" << "\t\t\t" << "Object_Reg(" << i->fetch.reg << ") Property_Index(" << i->fetch.index << ") -> Output_Reg(" << i->fetch.reg << ")";
 +        break;
 +    case V4Instr::Store:
 +        INSTR_DUMP << "\t" << "Store" << "\t\t\t" << "Input_Reg(" << i->store.reg << ") -> Object_Reg(" << i->store.output << ") Property_Index(" << i->store.index << ")";
 +        break;
 +    case V4Instr::Copy:
 +        INSTR_DUMP << "\t" << "Copy" << "\t\t\t" << "Input_Reg(" << i->copy.src << ") -> Output_Reg(" << i->copy.reg << ")";
 +        break;
 +    case V4Instr::Jump:
 +        if (i->jump.reg != -1) {
 +            INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + i->jump.count) << ") [if false == Input_Reg(" << i->jump.reg << ")]";
 +        } else {
 +            INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + i->jump.count) << ")";
 +        }
 +        break;
 +    case V4Instr::BranchFalse:
 +        INSTR_DUMP << "\t" << "BranchFalse" << "\t\t" << "Address(" << (address + size() + i->branchop.offset) << ") [if false == Input_Reg(" << i->branchop.reg << ")]";
 +        break;
 +    case V4Instr::BranchTrue:
 +        INSTR_DUMP << "\t" << "BranchTrue" << "\t\t" << "Address(" << (address + size() + i->branchop.offset) << ") [if true == Input_Reg(" << i->branchop.reg << ")]";
 +        break;
 +    case V4Instr::Branch:
 +        INSTR_DUMP << "\t" << "Branch" << "\t\t\t" << "Address(" << (address + size() + i->branchop.offset) << ")";
 +        break;
 +    case V4Instr::InitString:
 +        INSTR_DUMP << "\t" << "InitString" << "\t\t" << "String_DataIndex(" << i->initstring.dataIdx << ") -> String_Slot(" << i->initstring.offset << ")";
 +        break;
 +    case V4Instr::Block:
 +        INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(i->blockop.block, 16).constData()  << ")";
 +        break;
 +    default:
 +        INSTR_DUMP << "\t" << "Unknown";
 +        break;
 +    }
 +}
 +
 +void Bytecode::dump(const char *start, const char *end) const
 +{
 +    const char *code = start;
 +    while (code < end) {
 +        const V4Instr *instr = reinterpret_cast<const V4Instr *>(code);
 +        dump(instr, code - start);
 +        code += V4Instr::size(instructionType(instr));
 +    }
 +}
 +
 +Bytecode::Bytecode()
 +{
 +#ifdef QML_THREADED_INTERPRETER
 +    decodeInstr = QV4Bindings::getDecodeInstrTable();
 +#endif
 +}
 +
 +V4Instr::Type Bytecode::instructionType(const V4Instr *instr) const
 +{
 +#ifdef QML_THREADED_INTERPRETER
 +    void *code = instr->common.code;
 +
 +#  define CHECK_V4_INSTR_CODE(I, FMT) \
 +    if (decodeInstr[static_cast<int>(V4Instr::I)] == code) \
 +        return V4Instr::I;
 +
 +    FOR_EACH_V4_INSTR(CHECK_V4_INSTR_CODE)
 +    Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid instruction address");
 +    return static_cast<V4Instr::Type>(0);
 +#  undef CHECK_V4_INSTR_CODE
 +#else
 +    return static_cast<V4Instr::Type>(instr->common.type);
 +#endif
 +
 +}
 +
 +void Bytecode::append(V4Instr::Type type, V4Instr &instr)
 +{
 +#ifdef QML_THREADED_INTERPRETER
 +    instr.common.code = decodeInstr[static_cast<int>(type)];
 +#else
 +    instr.common.type = type;
 +#endif
 +    d.append(reinterpret_cast<const char *>(&instr), V4Instr::size(type));
 +}
 +
 +int Bytecode::remove(int offset)
 +{
 +    const V4Instr *instr = reinterpret_cast<const V4Instr *>(d.begin() + offset);
 +    const int instrSize = V4Instr::size(instructionType(instr));
 +    d.remove(offset, instrSize);
 +    return instrSize;
 +}
 +
 +const V4Instr &Bytecode::operator[](int offset) const
 +{
 +    return *(reinterpret_cast<const V4Instr *>(d.begin() + offset));
 +}
 +
 +V4Instr &Bytecode::operator[](int offset)
 +{
 +    return *(reinterpret_cast<V4Instr *>(d.begin() + offset));
 +}
 +
 +}
 +
 +QT_END_NAMESPACE
index 8150eed,0000000..964c955
mode 100644,000000..100644
--- /dev/null
@@@ -1,432 -1,0 +1,435 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QV4INSTRUCTION_P_H
 +#define QV4INSTRUCTION_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/qbytearray.h>
 +#include <QtCore/qvector.h>
 +#include <QtCore/qvarlengtharray.h>
 +
 +#include <private/qqmlpropertycache_p.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +#define FOR_EACH_V4_INSTR(F) \
 +    F(Noop, common) \
 +    F(BindingId, id) \
 +    F(Subscribe, subscribeop) \
 +    F(SubscribeId, subscribeop) \
 +    F(FetchAndSubscribe, fetchAndSubscribe) \
 +    F(LoadId, load) \
 +    F(LoadScope, load) \
 +    F(LoadRoot, load) \
 +    F(LoadAttached, attached) \
 +    F(UnaryNot, unaryop) \
 +    F(UnaryMinusReal, unaryop) \
 +    F(UnaryMinusInt, unaryop) \
 +    F(UnaryPlusReal, unaryop) \
 +    F(UnaryPlusInt, unaryop) \
 +    F(ConvertBoolToInt, unaryop) \
 +    F(ConvertBoolToReal, unaryop) \
 +    F(ConvertBoolToString, unaryop) \
 +    F(ConvertIntToBool, unaryop) \
 +    F(ConvertIntToReal, unaryop) \
 +    F(ConvertIntToString, unaryop) \
 +    F(ConvertRealToBool, unaryop) \
 +    F(ConvertRealToInt, unaryop) \
 +    F(ConvertRealToString, unaryop) \
 +    F(ConvertStringToBool, unaryop) \
 +    F(ConvertStringToInt, unaryop) \
 +    F(ConvertStringToReal, unaryop) \
 +    F(ConvertStringToUrl, unaryop) \
++    F(ConvertStringToColor, unaryop) \
 +    F(ConvertUrlToBool, unaryop) \
 +    F(ConvertUrlToString, unaryop) \
++    F(ConvertColorToBool, unaryop) \
++    F(ConvertColorToString, unaryop) \
 +    F(ResolveUrl, unaryop) \
 +    F(MathSinReal, unaryop) \
 +    F(MathCosReal, unaryop) \
 +    F(MathRoundReal, unaryop) \
 +    F(MathFloorReal, unaryop) \
 +    F(MathPIReal, unaryop) \
 +    F(LoadReal, real_value) \
 +    F(LoadInt, int_value) \
 +    F(LoadBool, bool_value) \
 +    F(LoadString, string_value) \
 +    F(EnableV4Test, string_value) \
 +    F(TestV4Store, storetest) \
 +    F(BitAndInt, binaryop) \
 +    F(BitOrInt, binaryop) \
 +    F(BitXorInt, binaryop) \
 +    F(AddReal, binaryop) \
 +    F(AddString, binaryop) \
 +    F(SubReal, binaryop) \
 +    F(MulReal, binaryop) \
 +    F(DivReal, binaryop) \
 +    F(ModReal, binaryop) \
 +    F(LShiftInt, binaryop) \
 +    F(RShiftInt, binaryop) \
 +    F(URShiftInt, binaryop) \
 +    F(GtReal, binaryop) \
 +    F(LtReal, binaryop) \
 +    F(GeReal, binaryop) \
 +    F(LeReal, binaryop) \
 +    F(EqualReal, binaryop) \
 +    F(NotEqualReal, binaryop) \
 +    F(StrictEqualReal, binaryop) \
 +    F(StrictNotEqualReal, binaryop) \
 +    F(GtString, binaryop) \
 +    F(LtString, binaryop) \
 +    F(GeString, binaryop) \
 +    F(LeString, binaryop) \
 +    F(EqualString, binaryop) \
 +    F(NotEqualString, binaryop) \
 +    F(StrictEqualString, binaryop) \
 +    F(StrictNotEqualString, binaryop) \
 +    F(NewString, construct) \
 +    F(NewUrl, construct) \
 +    F(CleanupRegister, cleanup) \
 +    F(Copy, copy) \
 +    F(Fetch, fetch) \
 +    F(Store, store) \
 +    F(Jump, jump) \
 +    F(BranchTrue, branchop) \
 +    F(BranchFalse, branchop) \
 +    F(Branch, branchop) \
 +    F(Block, blockop) \
 +    /* Speculative property resolution */ \
 +    F(InitString, initstring)
 +
 +#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200)
 +#  define QML_THREADED_INTERPRETER
 +#endif
 +
 +#ifdef Q_ALIGNOF
 +#  define QML_V4_INSTR_ALIGN_MASK (Q_ALIGNOF(V4Instr) - 1)
 +#else
 +#  define QML_V4_INSTR_ALIGN_MASK (sizeof(void *) - 1)
 +#endif
 +
 +#define QML_V4_INSTR_ENUM(I, FMT) I,
 +#define QML_V4_INSTR_ADDR(I, FMT) &&op_##I,
 +#define QML_V4_INSTR_SIZE(I, FMT) ((sizeof(V4Instr::instr_##FMT) + QML_V4_INSTR_ALIGN_MASK) & ~QML_V4_INSTR_ALIGN_MASK)
 +
 +#ifdef QML_THREADED_INTERPRETER
 +#  define QML_V4_BEGIN_INSTR(I,FMT) op_##I:
 +#  define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const V4Instr *) code; goto *instr->common.code;
 +#  define QML_V4_INSTR_HEADER void *code;
 +#else
 +#  define QML_V4_BEGIN_INSTR(I,FMT) case V4Instr::I:
 +#  define QML_V4_END_INSTR(I,FMT) code += QML_V4_INSTR_SIZE(I, FMT); instr = (const V4Instr *) code; break;
 +#  define QML_V4_INSTR_HEADER quint8 type;
 +#endif
 +
 +class QObject;
 +class QQmlNotifier;
 +
 +namespace QQmlJS {
 +
 +union V4Instr {
 +    enum Type {
 +        FOR_EACH_V4_INSTR(QML_V4_INSTR_ENUM)
 +    };
 +
 +    static int size(Type type);
 +
 +    struct instr_common {
 +        QML_V4_INSTR_HEADER
 +    };
 +
 +    struct instr_id {
 +        QML_V4_INSTR_HEADER
 +        quint16 column;
 +        quint32 line;
 +    };
 +
 +    struct instr_init {
 +        QML_V4_INSTR_HEADER
 +        quint16 subscriptions;
 +        quint16 identifiers;
 +    };
 +
 +    struct instr_subscribeop {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        quint16 offset;
 +        quint32 index;
 +    };
 +
 +    struct instr_load {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        quint32 index;
 +    };
 +
 +    struct instr_attached {
 +        QML_V4_INSTR_HEADER
 +        qint8 output;
 +        qint8 reg;
 +        quint8 exceptionId;
 +        quint32 id;
 +    };
 +
 +    struct instr_store {
 +        QML_V4_INSTR_HEADER
 +        qint8 output;
 +        qint8 reg;
 +        quint8 exceptionId;
 +        quint32 index;
 +    };
 +
 +    struct instr_storetest {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        qint32 regType;
 +    };
 +
 +    struct instr_fetchAndSubscribe {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        quint8 exceptionId;
 +        quint8 valueType;
 +        quint16 subscription;
 +        QQmlPropertyRawData property;
 +    };
 +
 +    struct instr_fetch{
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        quint8 exceptionId;
 +        quint8 valueType;
 +        quint32 index;
 +    };
 +
 +    struct instr_copy {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        qint8 src;
 +    };
 +
 +    struct instr_construct {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +    };
 +
 +    struct instr_real_value {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        qreal value; // XXX Makes the instruction 12 bytes
 +    };
 +
 +    struct instr_int_value {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        int value;
 +    };
 +
 +    struct instr_bool_value {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        bool value;
 +    };
 +
 +    struct instr_string_value {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        quint16 length;
 +        quint32 offset;
 +    };
 +
 +    struct instr_binaryop {
 +        QML_V4_INSTR_HEADER
 +        qint8 output;
 +        qint8 left;
 +        qint8 right;
 +    };
 +
 +    struct instr_unaryop {
 +        QML_V4_INSTR_HEADER
 +        qint8 output;
 +        qint8 src;
 +    };
 +
 +    struct instr_jump {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        quint32 count;
 +    };
 +
 +    struct instr_find {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +        qint8 src;
 +        quint8 exceptionId;
 +        quint16 name;
 +        quint16 subscribeIndex;
 +    };
 +
 +    struct instr_cleanup {
 +        QML_V4_INSTR_HEADER
 +        qint8 reg;
 +    };
 +
 +    struct instr_initstring {
 +        QML_V4_INSTR_HEADER
 +        quint16 offset;
 +        quint32 dataIdx;
 +    };
 +
 +    struct instr_branchop {
 +        QML_V4_INSTR_HEADER
 +        quint8 reg;
 +        qint16 offset;
 +    };
 +
 +    struct instr_blockop {
 +        QML_V4_INSTR_HEADER
 +        quint32 block;
 +    };
 +
 +    instr_common common;
 +    instr_id id;
 +    instr_init init;
 +    instr_subscribeop subscribeop;
 +    instr_load load;
 +    instr_attached attached;
 +    instr_store store;
 +    instr_storetest storetest;
 +    instr_fetchAndSubscribe fetchAndSubscribe;
 +    instr_fetch fetch;
 +    instr_copy copy;
 +    instr_construct construct;
 +    instr_real_value real_value;
 +    instr_int_value int_value;
 +    instr_bool_value bool_value;
 +    instr_string_value string_value;
 +    instr_binaryop binaryop;
 +    instr_unaryop unaryop;
 +    instr_jump jump;
 +    instr_find find;
 +    instr_cleanup cleanup;
 +    instr_initstring initstring;
 +    instr_branchop branchop;
 +    instr_blockop blockop;
 +};
 +
 +template<int N>
 +struct V4InstrMeta {
 +};
 +
 +#define QML_V4_INSTR_META_TEMPLATE(I, FMT) \
 +    template<> struct V4InstrMeta<(int)V4Instr::I> { \
 +        enum { Size = QML_V4_INSTR_SIZE(I, FMT) }; \
 +        typedef V4Instr::instr_##FMT DataType; \
 +        static const DataType &data(const V4Instr &instr) { return instr.FMT; } \
 +        static void setData(V4Instr &instr, const DataType &v) { instr.FMT = v; } \
 +    };
 +FOR_EACH_V4_INSTR(QML_V4_INSTR_META_TEMPLATE);
 +#undef QML_V4_INSTR_META_TEMPLATE
 +
 +template<int Instr>
 +class V4InstrData : public V4InstrMeta<Instr>::DataType
 +{
 +};
 +
 +class Bytecode
 +{
 +    Q_DISABLE_COPY(Bytecode)
 +
 +public:
 +    Bytecode();
 +
 +    const char *constData() const { return d.constData(); }
 +    int size() const { return d.size(); }
 +    int count() const { return d.count(); }
 +    void clear() { d.clear(); }
 +    bool isEmpty() const { return d.isEmpty(); }
 +    V4Instr::Type instructionType(const V4Instr *instr) const;
 +
 +    template <int Instr>
 +    void append(const V4InstrData<Instr> &data)
 +    {
 +        V4Instr genericInstr;
 +        V4InstrMeta<Instr>::setData(genericInstr, data);
 +        return append(static_cast<V4Instr::Type>(Instr), genericInstr);
 +    }
 +    void append(V4Instr::Type type, V4Instr &instr);
 +
 +    int remove(int index);
 +
 +    const V4Instr &operator[](int offset) const;
 +    V4Instr &operator[](int offset);
 +
 +    void dump(const char *start, const char *end) const;
 +
 +private:
 +    void dump(const V4Instr *instr, int = -1) const;
 +
 +    QVarLengthArray<char, 4 * 1024> d;
 +#ifdef QML_THREADED_INTERPRETER
 +    void **decodeInstr;
 +#endif
 +};
 +
 +}
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QV4INSTRUCTION_P_H
 +
index be82214,0000000..3b33898
mode 100644,000000..100644
--- /dev/null
@@@ -1,882 -1,0 +1,883 @@@
-     return ty == IR::StringType || ty == IR::UrlType;
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qv4ir_p.h"
 +
 +#include <QtCore/qtextstream.h>
 +#include <QtCore/qdebug.h>
 +#include <math.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +namespace QQmlJS {
 +namespace IR {
 +
 +inline const char *typeName(Type t)
 +{
 +    switch (t) {
 +    case InvalidType: return "invalid";
 +    case UndefinedType: return "undefined";
 +    case NullType: return "null";
 +    case VoidType: return "void";
 +    case StringType: return "string";
 +    case UrlType: return "url";
++    case ColorType: return "color";
 +    case SGAnchorLineType: return "SGAnchorLine";
 +    case AttachType: return "AttachType";
 +    case ObjectType: return "object";
 +    case BoolType: return "bool";
 +    case IntType: return "int";
 +    case RealType: return "qreal";
 +    case RealNaNType: return "NaN";
 +    default: return "invalid";
 +    }
 +}
 +
 +inline bool isNumberType(IR::Type ty)
 +{
 +    return ty >= IR::FirstNumberType;
 +}
 +
 +inline bool isStringType(IR::Type ty)
 +{
++    return ty == IR::StringType || ty == IR::UrlType || ty == IR::ColorType;
 +}
 +
 +IR::Type maxType(IR::Type left, IR::Type right)
 +{
 +    if (isStringType(left) && isStringType(right)) {
 +        // String promotions (url to string) are more specific than
 +        // identity conversions (AKA left == right). That's because
 +        // we want to ensure we convert urls to strings in binary
 +        // expressions.
 +        return IR::StringType;
 +    } else if (left == right)
 +        return left;
 +    else if (isNumberType(left) && isNumberType(right))
 +        return qMax(left, right);
 +    else if ((isNumberType(left) && isStringType(right)) ||
 +             (isNumberType(right) && isStringType(left)))
 +        return IR::StringType;
 +    else
 +        return IR::InvalidType;
 +}
 +
 +
 +const char *opname(AluOp op)
 +{
 +    switch (op) {
 +    case OpInvalid: return "?";
 +
 +    case OpIfTrue: return "(bool)";
 +    case OpNot: return "!";
 +    case OpUMinus: return "-";
 +    case OpUPlus: return "+";
 +    case OpCompl: return "~";
 +
 +    case OpBitAnd: return "&";
 +    case OpBitOr: return "|";
 +    case OpBitXor: return "^";
 +
 +    case OpAdd: return "+";
 +    case OpSub: return "-";
 +    case OpMul: return "*";
 +    case OpDiv: return "/";
 +    case OpMod: return "%";
 +
 +    case OpLShift: return "<<";
 +    case OpRShift: return ">>";
 +    case OpURShift: return ">>>";
 +
 +    case OpGt: return ">";
 +    case OpLt: return "<";
 +    case OpGe: return ">=";
 +    case OpLe: return "<=";
 +    case OpEqual: return "==";
 +    case OpNotEqual: return "!=";
 +    case OpStrictEqual: return "===";
 +    case OpStrictNotEqual: return "!==";
 +
 +    case OpAnd: return "&&";
 +    case OpOr: return "||";
 +
 +    default: return "?";
 +
 +    } // switch
 +}
 +
 +AluOp binaryOperator(int op)
 +{
 +    switch (static_cast<QSOperator::Op>(op)) {
 +    case QSOperator::Add: return OpAdd;
 +    case QSOperator::And: return OpAnd;
 +    case QSOperator::BitAnd: return OpBitAnd;
 +    case QSOperator::BitOr: return OpBitOr;
 +    case QSOperator::BitXor: return OpBitXor;
 +    case QSOperator::Div: return OpDiv;
 +    case QSOperator::Equal: return OpEqual;
 +    case QSOperator::Ge: return OpGe;
 +    case QSOperator::Gt: return OpGt;
 +    case QSOperator::Le: return OpLe;
 +    case QSOperator::LShift: return OpLShift;
 +    case QSOperator::Lt: return OpLt;
 +    case QSOperator::Mod: return OpMod;
 +    case QSOperator::Mul: return OpMul;
 +    case QSOperator::NotEqual: return OpNotEqual;
 +    case QSOperator::Or: return OpOr;
 +    case QSOperator::RShift: return OpRShift;
 +    case QSOperator::StrictEqual: return OpStrictEqual;
 +    case QSOperator::StrictNotEqual: return OpStrictNotEqual;
 +    case QSOperator::Sub: return OpSub;
 +    case QSOperator::URShift: return OpURShift;
 +    default: return OpInvalid;
 +    }
 +}
 +
 +void Const::dump(QTextStream &out)
 +{
 +    out << value;
 +}
 +
 +void String::dump(QTextStream &out)
 +{
 +    out << '"' << escape(value) << '"';
 +}
 +
 +QString String::escape(const QStringRef &s)
 +{
 +    QString r;
 +    for (int i = 0; i < s.length(); ++i) {
 +        const QChar ch = s.at(i);
 +        if (ch == QLatin1Char('\n'))
 +            r += QLatin1String("\\n");
 +        else if (ch == QLatin1Char('\r'))
 +            r += QLatin1String("\\r");
 +        else if (ch == QLatin1Char('\\'))
 +            r += QLatin1String("\\\\");
 +        else if (ch == QLatin1Char('"'))
 +            r += QLatin1String("\\\"");
 +        else if (ch == QLatin1Char('\''))
 +            r += QLatin1String("\\'");
 +        else
 +            r += ch;
 +    }
 +    return r;
 +}
 +
 +void Name::init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column)
 +{
 +    this->type = type;
 +    this->base = base;
 +    this->id = id;
 +    this->symbol = symbol;
 +    this->ptr = 0;
 +    this->property = 0;
 +    this->storage = MemberStorage;
 +    this->builtin = NoBuiltinSymbol;
 +    this->line = line;
 +    this->column = column;
 +
 +    if (id->length() == 8 && *id == QLatin1String("Math.sin")) {
 +        builtin = MathSinBultinFunction;
 +    } else if (id->length() == 8 && *id == QLatin1String("Math.cos")) {
 +        builtin = MathCosBultinFunction;
 +    } else if (id->length() == 10 && *id == QLatin1String("Math.round")) {
 +        builtin = MathRoundBultinFunction;
 +    } else if (id->length() == 10 && *id == QLatin1String("Math.floor)")) {
 +        builtin = MathFloorBultinFunction;
 +    } else if (id->length() == 7 && *id == QLatin1String("Math.PI")) {
 +        builtin = MathPIBuiltinConstant;
 +        this->type = RealType;
 +    }
 +}
 +
 +void Name::dump(QTextStream &out)
 +{
 +    if (base) {
 +        base->dump(out);
 +        out << '.';
 +    }
 +
 +    out << *id;
 +}
 +
 +void Temp::dump(QTextStream &out)
 +{
 +    out << 't' << index;
 +}
 +
 +void Unop::dump(QTextStream &out)
 +{
 +    out << opname(op);
 +    expr->dump(out);
 +}
 +
 +Type Unop::typeForOp(AluOp op, Expr *expr)
 +{
 +    switch (op) {
 +    case OpIfTrue: return BoolType;
 +    case OpNot: return BoolType;
 +
 +    case OpUMinus:
 +    case OpUPlus:
 +    case OpCompl:
 +        return maxType(expr->type, RealType);
 +
 +    default:
 +        break;
 +    }
 +
 +    return InvalidType;
 +}
 +
 +void Binop::dump(QTextStream &out)
 +{
 +    left->dump(out);
 +    out << ' ' << opname(op) << ' ';
 +    right->dump(out);
 +}
 +
 +Type Binop::typeForOp(AluOp op, Expr *left, Expr *right)
 +{
 +    if (! (left && right))
 +        return InvalidType;
 +
 +    switch (op) {
 +    case OpInvalid:
 +        return InvalidType;
 +
 +    // unary operators
 +    case OpIfTrue:
 +    case OpNot:
 +    case OpUMinus:
 +    case OpUPlus:
 +    case OpCompl:
 +        return InvalidType;
 +
 +    // bit fields
 +    case OpBitAnd:
 +    case OpBitOr:
 +    case OpBitXor:
 +        return IntType;
 +
 +    case OpAdd:
 +        if (left->type == StringType)
 +            return StringType;
 +        return RealType;
 +
 +    case OpSub:
 +    case OpMul:
 +    case OpDiv:
 +    case OpMod:
 +        return RealType;
 +
 +    case OpLShift:
 +    case OpRShift:
 +    case OpURShift:
 +        return IntType;
 +
 +    case OpAnd:
 +    case OpOr:
 +        return BoolType;
 +
 +    case OpGt:
 +    case OpLt:
 +    case OpGe:
 +    case OpLe:
 +    case OpEqual:
 +    case OpNotEqual:
 +    case OpStrictEqual:
 +    case OpStrictNotEqual:
 +        return BoolType;
 +    } // switch
 +
 +    return InvalidType;
 +}
 +
 +void Call::dump(QTextStream &out)
 +{
 +    base->dump(out);
 +    out << '(';
 +    for (ExprList *it = args; it; it = it->next) {
 +        if (it != args)
 +            out << ", ";
 +        it->expr->dump(out);
 +    }
 +    out << ')';
 +}
 +
 +Type Call::typeForFunction(Expr *base)
 +{
 +    if (! base)
 +        return InvalidType;
 +
 +    if (Name *name = base->asName()) {
 +        switch (name->builtin) {
 +        case MathSinBultinFunction:
 +        case MathCosBultinFunction:
 +            return RealType;
 +
 +        case MathRoundBultinFunction:
 +        case MathFloorBultinFunction:
 +            return IntType;
 +
 +        case NoBuiltinSymbol:
 +        case MathPIBuiltinConstant:
 +            break;
 +        }
 +    } // switch
 +
 +    return InvalidType;
 +}
 +
 +void Exp::dump(QTextStream &out, Mode)
 +{
 +    out << "(void) ";
 +    expr->dump(out);
 +    out << ';';
 +}
 +
 +void Move::dump(QTextStream &out, Mode)
 +{
 +    target->dump(out);
 +    out << " = ";
 +    if (source->type != target->type)
 +        out << typeName(source->type) << "_to_" << typeName(target->type) << '(';
 +    source->dump(out);
 +    if (source->type != target->type)
 +        out << ')';
 +    out << ';';
 +}
 +
 +void Jump::dump(QTextStream &out, Mode mode)
 +{
 +    Q_UNUSED(mode);
 +    out << "goto " << 'L' << target << ';';
 +}
 +
 +void CJump::dump(QTextStream &out, Mode mode)
 +{
 +    Q_UNUSED(mode);
 +    out << "if (";
 +    cond->dump(out);
 +    out << ") goto " << 'L' << iftrue << "; else goto " << 'L' << iffalse << ';';
 +}
 +
 +void Ret::dump(QTextStream &out, Mode)
 +{
 +    out << "return";
 +    if (expr) {
 +        out << ' ';
 +        expr->dump(out);
 +    }
 +    out << ';';
 +}
 +
 +Function::~Function()
 +{
 +    qDeleteAll(basicBlocks);
 +}
 +
 +QString *Function::newString(const QString &text)
 +{
 +    return pool->NewString(text);
 +}
 +
 +BasicBlock *Function::newBasicBlock()
 +{
 +    const int index = basicBlocks.size();
 +    return i(new BasicBlock(this, index));
 +}
 +
 +void Function::dump(QTextStream &out)
 +{
 +    out << "function () {" << endl;
 +    foreach (BasicBlock *bb, basicBlocks) {
 +        bb->dump(out);
 +    }
 +    out << '}' << endl;
 +}
 +
 +Temp *BasicBlock::TEMP(Type type, int index) 
 +{ 
 +    Temp *e = function->pool->New<Temp>();
 +    e->init(type, index);
 +    return e;
 +}
 +
 +Temp *BasicBlock::TEMP(Type type) 
 +{ 
 +    return TEMP(type, function->tempCount++); 
 +}
 +
 +Expr *BasicBlock::CONST(double value) 
 +{ 
 +    return CONST(IR::RealType, value); 
 +}
 +
 +Expr *BasicBlock::CONST(Type type, double value) 
 +{ 
 +    Const *e = function->pool->New<Const>();
 +    e->init(type, value);
 +    return e;
 +}
 +
 +Expr *BasicBlock::STRING(const QStringRef &value)
 +{
 +    String *e = function->pool->New<String>();
 +    e->init(value);
 +    return e;
 +}
 +
 +Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column)
 +{ 
 +    return NAME(0, id, line, column);
 +}
 +
 +Name *BasicBlock::NAME(Name *base, const QString &id, quint32 line, quint32 column)
 +{ 
 +    Name *e = function->pool->New<Name>();
 +    e->init(base, InvalidType,
 +            function->newString(id),
 +            Name::Unbound, line, column);
 +    return e;
 +}
 +
 +Name *BasicBlock::SYMBOL(Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage,
 +                         quint32 line, quint32 column)
 +{
 +    Name *name = SYMBOL(/*base = */ 0, type, id, meta, property, line, column);
 +    name->storage = storage;
 +    return name;
 +}
 +
 +Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage,
 +                         quint32 line, quint32 column)
 +{
 +    Name *name = function->pool->New<Name>();
 +    name->init(base, type, function->newString(id),
 +               Name::Property, line, column);
 +    name->meta = meta;
 +    name->property = property;
 +    name->storage = storage;
 +    return name;
 +}
 +
 +Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property,
 +                         quint32 line, quint32 column)
 +{
 +    Name *name = function->pool->New<Name>();
 +    name->init(base, type, function->newString(id),
 +               Name::Property, line, column);
 +    name->meta = meta;
 +    name->property = property;
 +    return name;
 +}
 +
 +Name *BasicBlock::ID_OBJECT(const QString &id, const QQmlScript::Object *object, quint32 line, quint32 column)
 +{
 +    Name *name = function->pool->New<Name>();
 +    name->init(/*base = */ 0, IR::ObjectType,
 +               function->newString(id),
 +               Name::IdObject, line, column);
 +    name->idObject = object;
 +    name->property = 0;
 +    name->storage = Name::IdStorage;
 +    return name;
 +}
 +
 +Name *BasicBlock::ATTACH_TYPE(const QString &id, const QQmlType *attachType, Name::Storage storage,
 +                              quint32 line, quint32 column)
 +{ 
 +    Name *name = function->pool->New<Name>();
 +    name->init(/*base = */ 0, IR::AttachType,
 +               function->newString(id),
 +               Name::AttachType, line, column);
 +    name->declarativeType = attachType;
 +    name->storage = storage;
 +    return name;
 +}
 +
 +
 +Expr *BasicBlock::UNOP(AluOp op, Expr *expr) 
 +{ 
 +    Unop *e = function->pool->New<Unop>();
 +    e->init(op, expr);
 +    return e;
 +}
 +
 +Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right)
 +{
 +    if (left && right) {
 +        if (Const *c1 = left->asConst()) {
 +            if (Const *c2 = right->asConst()) {
 +                switch (op) {
 +                case OpAdd: return CONST(c1->value + c2->value);
 +                case OpAnd: return CONST(c1->value ? c2->value : 0);
 +                case OpBitAnd: return CONST(int(c1->value) & int(c2->value));
 +                case OpBitOr: return CONST(int(c1->value) | int(c2->value));
 +                case OpBitXor: return CONST(int(c1->value) ^ int(c2->value));
 +                case OpDiv: return CONST(c1->value / c2->value);
 +                case OpEqual: return CONST(c1->value == c2->value);
 +                case OpGe: return CONST(c1->value >= c2->value);
 +                case OpGt: return CONST(c1->value > c2->value);
 +                case OpLe: return CONST(c1->value <= c2->value);
 +                case OpLShift: return CONST(int(c1->value) << int(c2->value));
 +                case OpLt: return CONST(c1->value < c2->value);
 +                case OpMod: return CONST(::fmod(c1->value, c2->value));
 +                case OpMul: return CONST(c1->value * c2->value);
 +                case OpNotEqual: return CONST(c1->value != c2->value);
 +                case OpOr: return CONST(c1->value ? c1->value : c2->value);
 +                case OpRShift: return CONST(int(c1->value) >> int(c2->value));
 +                case OpStrictEqual: return CONST(c1->value == c2->value);
 +                case OpStrictNotEqual: return CONST(c1->value != c2->value);
 +                case OpSub: return CONST(c1->value - c2->value);
 +                case OpURShift: return CONST(unsigned(c1->value) >> int(c2->value));
 +
 +                case OpIfTrue: // unary ops
 +                case OpNot:
 +                case OpUMinus:
 +                case OpUPlus:
 +                case OpCompl:
 +                case OpInvalid:
 +                    break;
 +                }
 +            }
 +        }
 +    }
 +
 +    Binop *e = function->pool->New<Binop>();
 +    e->init(op, left, right);
 +    return e;
 +}
 +
 +Expr *BasicBlock::CALL(Expr *base, ExprList *args)
 +{ 
 +    Call *e = function->pool->New<Call>();
 +    e->init(base, args);
 +    return e;
 +}
 +
 +Stmt *BasicBlock::EXP(Expr *expr) 
 +{ 
 +    Exp *s = function->pool->New<Exp>();
 +    s->init(expr);
 +    statements.append(s);
 +    return s;
 +}
 +
 +Stmt *BasicBlock::MOVE(Expr *target, Expr *source, bool isMoveForReturn) 
 +{ 
 +    Move *s = function->pool->New<Move>();
 +    s->init(target, source, isMoveForReturn);
 +    statements.append(s);
 +    return s;
 +}
 +
 +Stmt *BasicBlock::JUMP(BasicBlock *target) 
 +{
 +    if (isTerminated())
 +        return 0;
 +
 +    Jump *s = function->pool->New<Jump>();
 +    s->init(target);
 +    statements.append(s);
 +    return s;
 +}
 +
 +Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) 
 +{
 +    if (isTerminated())
 +        return 0;
 +
 +    CJump *s = function->pool->New<CJump>();
 +    s->init(cond, iftrue, iffalse);
 +    statements.append(s);
 +    return s;
 +}
 +
 +Stmt *BasicBlock::RET(Expr *expr, Type type, quint32 line, quint32 column)
 +{
 +    if (isTerminated())
 +        return 0;
 +
 +    Ret *s = function->pool->New<Ret>();
 +    s->init(expr, type, line, column);
 +    statements.append(s);
 +    return s;
 +}
 +
 +void BasicBlock::dump(QTextStream &out)
 +{
 +    out << 'L' << this << ':' << endl;
 +    foreach (Stmt *s, statements) {
 +        out << '\t';
 +        s->dump(out);
 +        out << endl;
 +    }
 +}
 +
 +#ifdef DEBUG_IR_STRUCTURE
 +
 +static const char *symbolname(Name::Symbol s) 
 +{
 +    switch (s) {
 +    case Name::Unbound:
 +        return "Unbound";
 +    case Name::IdObject:
 +        return "IdObject";
 +    case Name::AttachType:
 +        return "AttachType";
 +    case Name::Object:
 +        return "Object";
 +    case Name::Property:
 +        return "Property";
 +    case Name::Slot:
 +        return "Slot";
 +    default:
 +        Q_ASSERT(!"Unreachable");
 +        return "Unknown"; 
 +    }
 +}
 +
 +static const char *storagename(Name::Storage s)
 +{
 +    switch (s) {
 +    case Name::MemberStorage:
 +        return "MemberStorage";
 +    case Name::IdStorage:
 +        return "IdStorage";
 +    case Name::RootStorage:
 +        return "RootStorage";
 +    case Name::ScopeStorage:
 +        return "ScopeStorage";
 +    default:
 +        Q_ASSERT(!"Unreachable");
 +        return "UnknownStorage";
 +    }
 +}
 +
 +IRDump::IRDump()
 +: indentSize(0)
 +{
 +}
 +
 +void IRDump::inc()
 +{
 +    indentSize++;
 +    indentData = QByteArray(indentSize * 4, ' ');
 +}
 +
 +void IRDump::dec()
 +{
 +    indentSize--;
 +    indentData = QByteArray(indentSize * 4, ' ');
 +}
 +
 +void IRDump::dec();
 +
 +void IRDump::expression(QQmlJS::IR::Expr *e)
 +{
 +    inc();
 +
 +    e->accept(this);
 +
 +    dec();
 +}
 +
 +void IRDump::basicblock(QQmlJS::IR::BasicBlock *b)
 +{
 +    inc();
 +
 +    qWarning().nospace() << indent() << "BasicBlock " << b << " {";
 +    for (int ii = 0; ii < b->statements.count(); ++ii) {
 +        statement(b->statements.at(ii));
 +        if (ii != (b->statements.count() - 1))
 +            qWarning();
 +    }
 +    qWarning().nospace() << indent() << "}";
 +
 +    dec();
 +}
 +
 +void IRDump::statement(QQmlJS::IR::Stmt *s)
 +{
 +    inc();
 +
 +    s->accept(this);
 +
 +    dec();
 +}
 +
 +void IRDump::function(QQmlJS::IR::Function *f)
 +{
 +    inc();
 +
 +    qWarning().nospace() << indent() << "Function {";
 +    for (int ii = 0; ii < f->basicBlocks.count(); ++ii) {
 +        basicblock(f->basicBlocks.at(ii));
 +    }
 +    qWarning().nospace() << indent() << "}";
 +
 +    dec();
 +}
 +
 +const char *IRDump::indent()
 +{
 +    return indentData.constData();
 +}
 +
 +void IRDump::visitConst(QQmlJS::IR::Const *e)
 +{
 +    qWarning().nospace() << indent() << "Const:Expr { type: " << typeName(e->type) << ", value: " << e->value << "}";
 +}
 +
 +void IRDump::visitString(QQmlJS::IR::String *e)
 +{
 +    qWarning().nospace() << indent() << "String:Expr { type: " << typeName(e->type) << ", value: " << e->value << "}";
 +}
 +
 +static void namedumprecur(QQmlJS::IR::Name *e, const char *indent) 
 +{
 +    if (e->base) namedumprecur(e->base, indent);
 +    qWarning().nospace() << indent << "    { type: " << typeName(e->type) << ", symbol: " << symbolname(e->symbol) << ", storage: " << storagename(e->storage) << ", id: " << e->id << "}";
 +}
 +
 +void IRDump::visitName(QQmlJS::IR::Name *e)
 +{
 +    qWarning().nospace() << indent() << "Name:Expr {";
 +    namedumprecur(e, indent());
 +    qWarning().nospace() << indent() << "}";
 +}
 +
 +void IRDump::visitTemp(QQmlJS::IR::Temp *e)
 +{
 +    qWarning().nospace() << indent() << "Temp:Expr { type: " << typeName(e->type) << ", index: " << e->index << " }";
 +}
 +
 +void IRDump::visitUnop(QQmlJS::IR::Unop *e)
 +{
 +    qWarning().nospace() << indent() << "Unop:Expr { ";
 +    qWarning().nospace() << indent() << "    type: " << typeName(e->type) << ", op: " << opname(e->op);
 +    qWarning().nospace() << indent() << "    expr: {";
 +    expression(e->expr);
 +    qWarning().nospace() << indent() << "    }";
 +    qWarning().nospace() << indent() << "}";
 +}
 +
 +void IRDump::visitBinop(QQmlJS::IR::Binop *e)
 +{
 +    qWarning().nospace() << indent() << "Binop:Expr { ";
 +    qWarning().nospace() << indent() << "    type: " << typeName(e->type) << ", op: " << opname(e->op);
 +    qWarning().nospace() << indent() << "    left: {";
 +    inc();
 +    expression(e->left);
 +    dec();
 +    qWarning().nospace() << indent() << "    },";
 +    qWarning().nospace() << indent() << "    right: {";
 +    inc();
 +    expression(e->right);
 +    dec();
 +    qWarning().nospace() << indent() << "    }";
 +    qWarning().nospace() << indent() << "}";
 +}
 +
 +void IRDump::visitCall(QQmlJS::IR::Call *e)
 +{
 +    Q_UNUSED(e);
 +    qWarning().nospace() << indent() << "Exp::Call { }";
 +}
 +
 +void IRDump::visitExp(QQmlJS::IR::Exp *s)
 +{
 +    qWarning().nospace() << indent() << "Exp:Stmt {";
 +    expression(s->expr);
 +    qWarning().nospace() << indent() << "}";
 +}
 +
 +void IRDump::visitMove(QQmlJS::IR::Move *s)
 +{
 +    qWarning().nospace() << indent() << "Move:Stmt {";
 +    qWarning().nospace() << indent() << "    isMoveForReturn: " << s->isMoveForReturn;
 +    qWarning().nospace() << indent() << "    target: {";
 +    inc();
 +    expression(s->target);
 +    dec();
 +    qWarning().nospace() << indent() << "    },";
 +    qWarning().nospace() << indent() << "    source: {";
 +    inc();
 +    expression(s->source);
 +    dec();
 +    qWarning().nospace() << indent() << "    }";
 +    qWarning().nospace() << indent() << "}";
 +}
 +
 +void IRDump::visitJump(QQmlJS::IR::Jump *s)
 +{
 +    qWarning().nospace() << indent() << "Jump:Stmt { BasicBlock(" << s->target << ") }";
 +}
 +
 +void IRDump::visitCJump(QQmlJS::IR::CJump *s)
 +{
 +    qWarning().nospace() << indent() << "CJump:Stmt {";
 +    qWarning().nospace() << indent() << "    cond: {";
 +    inc();
 +    expression(s->cond);
 +    dec();
 +    qWarning().nospace() << indent() << "    }";
 +    qWarning().nospace() << indent() << "    iftrue: BasicBlock(" << s->iftrue << ")";
 +    qWarning().nospace() << indent() << "    iffalse: BasicBlock(" << s->iffalse << ")";
 +    qWarning().nospace() << indent() << "}";
 +}
 +
 +void IRDump::visitRet(QQmlJS::IR::Ret *s)
 +{
 +    qWarning().nospace() << indent() << "Ret:Stmt {";
 +    qWarning().nospace() << indent() << "    type: " << typeName(s->type);
 +    expression(s->expr);
 +    qWarning().nospace() << indent() << "}";
 +}
 +#endif
 +
 +} // end of namespace IR
 +} // end of namespace QQmlJS
 +
 +QT_END_NAMESPACE
index 48a08ad,0000000..e80c7e2
mode 100644,000000..100644
--- /dev/null
@@@ -1,604 -1,0 +1,605 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QV4IR_P_H
 +#define QV4IR_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/qqmljsast_p.h>
 +#include <private/qqmljsengine_p.h>
 +#include <private/qqmlscript_p.h>
 +#include <private/qqmlimport_p.h>
 +#include <private/qqmlengine_p.h>
 +#include <private/qv4compiler_p.h>
 +
 +#include <private/qqmlpool_p.h>
 +#include <QtCore/qvarlengtharray.h>
 +
 +// #define DEBUG_IR_STRUCTURE
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QTextStream;
 +class QQmlType;
 +
 +namespace QQmlJS {
 +
 +namespace IR {
 +
 +struct BasicBlock;
 +struct Function;
 +
 +struct Stmt;
 +struct Expr;
 +
 +// expressions
 +struct Const;
 +struct String;
 +struct Name;
 +struct Temp;
 +struct Unop;
 +struct Binop;
 +struct Call;
 +
 +// statements
 +struct Exp;
 +struct Move;
 +struct Jump;
 +struct CJump;
 +struct Ret;
 +
 +enum AluOp {
 +    OpInvalid = 0,
 +
 +    OpIfTrue,
 +    OpNot,
 +    OpUMinus,
 +    OpUPlus,
 +    OpCompl,
 +
 +    OpBitAnd,
 +    OpBitOr,
 +    OpBitXor,
 +
 +    OpAdd,
 +    OpSub,
 +    OpMul,
 +    OpDiv,
 +    OpMod,
 +
 +    OpLShift,
 +    OpRShift,
 +    OpURShift,
 +
 +    OpGt,
 +    OpLt,
 +    OpGe,
 +    OpLe,
 +    OpEqual,
 +    OpNotEqual,
 +    OpStrictEqual,
 +    OpStrictNotEqual,
 +
 +    OpAnd,
 +    OpOr
 +};
 +AluOp binaryOperator(int op);
 +
 +enum Type {
 +    InvalidType,
 +    UndefinedType,
 +    NullType,
 +    VoidType,
 +    StringType,
 +    UrlType,
++    ColorType,
 +    SGAnchorLineType,
 +    AttachType,
 +    ObjectType,
 +
 +    FirstNumberType,
 +    BoolType = FirstNumberType,
 +    IntType,
 +    RealType,
 +    RealNaNType
 +};
 +Type maxType(IR::Type left, IR::Type right);
 +
 +struct ExprVisitor {
 +    virtual ~ExprVisitor() {}
 +    virtual void visitConst(Const *) {}
 +    virtual void visitString(String *) {}
 +    virtual void visitName(Name *) {}
 +    virtual void visitTemp(Temp *) {}
 +    virtual void visitUnop(Unop *) {}
 +    virtual void visitBinop(Binop *) {}
 +    virtual void visitCall(Call *) {}
 +};
 +
 +struct StmtVisitor {
 +    virtual ~StmtVisitor() {}
 +    virtual void visitExp(Exp *) {}
 +    virtual void visitMove(Move *) {}
 +    virtual void visitJump(Jump *) {}
 +    virtual void visitCJump(CJump *) {}
 +    virtual void visitRet(Ret *) {}
 +};
 +
 +struct Expr: QQmlPool::POD {
 +    Type type;
 +
 +    Expr(): type(InvalidType) {}
 +    virtual ~Expr() {}
 +    virtual void accept(ExprVisitor *) = 0;
 +    virtual Const *asConst() { return 0; }
 +    virtual String *asString() { return 0; }
 +    virtual Name *asName() { return 0; }
 +    virtual Temp *asTemp() { return 0; }
 +    virtual Unop *asUnop() { return 0; }
 +    virtual Binop *asBinop() { return 0; }
 +    virtual Call *asCall() { return 0; }
 +    virtual void dump(QTextStream &out) = 0;
 +};
 +
 +struct ExprList: QQmlPool::POD {
 +    Expr *expr;
 +    ExprList *next;
 +
 +    void init(Expr *expr, ExprList *next = 0)
 +    {
 +        this->expr = expr;
 +        this->next = next;
 +    }
 +};
 +
 +struct Const: Expr {
 +    double value;
 +
 +    void init(Type type, double value)
 +    {
 +        this->type = type;
 +        this->value = value;
 +    }
 +
 +    virtual void accept(ExprVisitor *v) { v->visitConst(this); }
 +    virtual Const *asConst() { return this; }
 +
 +    virtual void dump(QTextStream &out);
 +};
 +
 +struct String: Expr {
 +    QStringRef value;
 +
 +    void init(const QStringRef &value)
 +    {
 +        this->type = StringType;
 +        this->value = value;
 +    }
 +
 +    virtual void accept(ExprVisitor *v) { v->visitString(this); }
 +    virtual String *asString() { return this; }
 +
 +    virtual void dump(QTextStream &out);
 +    static QString escape(const QStringRef &s);
 +};
 +
 +enum BuiltinSymbol {
 +    NoBuiltinSymbol,
 +    MathSinBultinFunction,
 +    MathCosBultinFunction,
 +    MathRoundBultinFunction,
 +    MathFloorBultinFunction,
 +
 +    MathPIBuiltinConstant
 +};
 +
 +struct Name: Expr {
 +    enum Symbol {
 +        Unbound,
 +        IdObject,      // This is a load of a id object.  Storage will always be IdStorage
 +        AttachType,    // This is a load of an attached object 
 +        Object,        // XXX what is this for?
 +        Property,      // This is a load of a regular property
 +        Slot           // XXX what is this for?
 +    };
 +
 +    enum Storage {
 +        MemberStorage, // This is a property of a previously fetched object
 +        IdStorage,     // This is a load of a id object.  Symbol will always be IdObject
 +        RootStorage,   // This is a property of the root object
 +        ScopeStorage   // This is a property of the scope object
 +    };
 +
 +    Name *base;
 +    const QString *id;
 +    Symbol symbol;
 +    union {
 +        void *ptr;
 +        const QMetaObject *meta;
 +        const QQmlType *declarativeType;
 +        const QQmlScript::Object *idObject;
 +    };
 +    QQmlPropertyData *property;
 +    Storage storage;
 +    BuiltinSymbol builtin;
 +    quint32 line;
 +    quint32 column;
 +
 +    void init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column);
 +
 +    inline bool is(Symbol s) const { return s == symbol; }
 +    inline bool isNot(Symbol s) const { return s != symbol; }
 +
 +    virtual void accept(ExprVisitor *v) { v->visitName(this); }
 +    virtual Name *asName() { return this; }
 +
 +    virtual void dump(QTextStream &out);
 +};
 +
 +struct Temp: Expr {
 +    int index;
 +
 +    void init(Type type, int index)
 +    {
 +        this->type = type;
 +        this->index = index;
 +    }
 +
 +    virtual void accept(ExprVisitor *v) { v->visitTemp(this); }
 +    virtual Temp *asTemp() { return this; }
 +
 +    virtual void dump(QTextStream &out);
 +};
 +
 +struct Unop: Expr {
 +    AluOp op;
 +    Expr *expr;
 +
 +    void init(AluOp op, Expr *expr)
 +    {
 +        this->type = this->typeForOp(op, expr);
 +        this->op = op;
 +        this->expr = expr;
 +    }
 +
 +    virtual void accept(ExprVisitor *v) { v->visitUnop(this); }
 +    virtual Unop *asUnop() { return this; }
 +
 +    virtual void dump(QTextStream &out);
 +
 +private:
 +    static Type typeForOp(AluOp op, Expr *expr);
 +};
 +
 +struct Binop: Expr {
 +    AluOp op;
 +    Expr *left;
 +    Expr *right;
 +
 +    void init(AluOp op, Expr *left, Expr *right)
 +    {
 +        this->type = typeForOp(op, left, right);
 +        this->op = op;
 +        this->left = left;
 +        this->right = right;
 +    }
 +
 +    virtual void accept(ExprVisitor *v) { v->visitBinop(this); }
 +    virtual Binop *asBinop() { return this; }
 +
 +    virtual void dump(QTextStream &out);
 +
 +private:
 +    static Type typeForOp(AluOp op, Expr *left, Expr *right);
 +};
 +
 +struct Call: Expr {
 +    Expr *base;
 +    ExprList *args;
 +
 +    void init(Expr *base, ExprList *args)
 +    {
 +        this->type = typeForFunction(base);
 +        this->base = base;
 +        this->args = args;
 +    }
 +
 +    Expr *onlyArgument() const {
 +        if (args && ! args->next)
 +            return args->expr;
 +        return 0;
 +    }
 +
 +    virtual void accept(ExprVisitor *v) { v->visitCall(this); }
 +    virtual Call *asCall() { return this; }
 +
 +    virtual void dump(QTextStream &out);
 +
 +private:
 +    static Type typeForFunction(Expr *base);
 +};
 +
 +struct Stmt: QQmlPool::POD {
 +    enum Mode {
 +        HIR,
 +        MIR
 +    };
 +
 +    virtual ~Stmt() {}
 +    virtual Stmt *asTerminator() { return 0; }
 +
 +    virtual void accept(StmtVisitor *) = 0;
 +    virtual Exp *asExp() { return 0; }
 +    virtual Move *asMove() { return 0; }
 +    virtual Jump *asJump() { return 0; }
 +    virtual CJump *asCJump() { return 0; }
 +    virtual Ret *asRet() { return 0; }
 +    virtual void dump(QTextStream &out, Mode mode = HIR) = 0;
 +};
 +
 +struct Exp: Stmt {
 +    Expr *expr;
 +
 +    void init(Expr *expr)
 +    {
 +        this->expr = expr;
 +    }
 +
 +    virtual void accept(StmtVisitor *v) { v->visitExp(this); }
 +    virtual Exp *asExp() { return this; }
 +
 +    virtual void dump(QTextStream &out, Mode);
 +};
 +
 +struct Move: Stmt {
 +    Expr *target;
 +    Expr *source;
 +    bool isMoveForReturn;
 +
 +    void init(Expr *target, Expr *source, bool isMoveForReturn)
 +    {
 +        this->target = target;
 +        this->source = source;
 +        this->isMoveForReturn = isMoveForReturn;
 +    }
 +
 +    virtual void accept(StmtVisitor *v) { v->visitMove(this); }
 +    virtual Move *asMove() { return this; }
 +
 +    virtual void dump(QTextStream &out, Mode);
 +};
 +
 +struct Jump: Stmt {
 +    BasicBlock *target;
 +
 +    void init(BasicBlock *target)
 +    {
 +        this->target = target;
 +    }
 +
 +    virtual Stmt *asTerminator() { return this; }
 +
 +    virtual void accept(StmtVisitor *v) { v->visitJump(this); }
 +    virtual Jump *asJump() { return this; }
 +
 +    virtual void dump(QTextStream &out, Mode mode);
 +};
 +
 +struct CJump: Stmt {
 +    Expr *cond;
 +    BasicBlock *iftrue;
 +    BasicBlock *iffalse;
 +
 +    void init(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse)
 +    {
 +        this->cond = cond;
 +        this->iftrue = iftrue;
 +        this->iffalse = iffalse;
 +    }
 +
 +    virtual Stmt *asTerminator() { return this; }
 +
 +    virtual void accept(StmtVisitor *v) { v->visitCJump(this); }
 +    virtual CJump *asCJump() { return this; }
 +
 +    virtual void dump(QTextStream &out, Mode mode);
 +};
 +
 +struct Ret: Stmt {
 +    Expr *expr;
 +    Type type;
 +    quint32 line;
 +    quint32 column;
 +
 +    void init(Expr *expr, Type type, quint32 line, quint32 column)
 +    {
 +        this->expr = expr;
 +        this->type = type;
 +        this->line = line;
 +        this->column = column;
 +    }
 +
 +    virtual Stmt *asTerminator() { return this; }
 +
 +    virtual void accept(StmtVisitor *v) { v->visitRet(this); }
 +    virtual Ret *asRet() { return this; }
 +
 +    virtual void dump(QTextStream &out, Mode);
 +};
 +
 +struct Function {
 +    QQmlPool *pool;
 +    QVarLengthArray<BasicBlock *, 8> basicBlocks;
 +    int tempCount;
 +
 +    Function(QQmlPool *pool)
 +      : pool(pool), tempCount(0) {}
 +
 +    ~Function();
 +
 +    BasicBlock *newBasicBlock();
 +    QString *newString(const QString &text);
 +
 +    inline BasicBlock *i(BasicBlock *block) { basicBlocks.append(block); return block; }
 +
 +    virtual void dump(QTextStream &out);
 +};
 +
 +struct BasicBlock {
 +    Function *function;
 +    int index;
 +    int offset;
 +    QVarLengthArray<Stmt *, 32> statements;
 +
 +    BasicBlock(Function *function, int index): function(function), index(index), offset(-1) {}
 +    ~BasicBlock() {}
 +
 +    template <typename Instr> inline Instr i(Instr i) { statements.append(i); return i; }
 +
 +    inline bool isEmpty() const {
 +        return statements.isEmpty();
 +    }
 +
 +    inline Stmt *terminator() const {
 +        if (! statements.isEmpty() && statements.at(statements.size() - 1)->asTerminator() != 0)
 +            return statements.at(statements.size() - 1);
 +        return 0;
 +    }
 +
 +    inline bool isTerminated() const {
 +        if (terminator() != 0)
 +            return true;
 +        return false;
 +    }
 +
 +    Temp *TEMP(Type type, int index);
 +    Temp *TEMP(Type type);
 +
 +    Expr *CONST(double value);
 +    Expr *CONST(Type type, double value);
 +    Expr *STRING(const QStringRef &value);
 +
 +    Name *NAME(const QString &id, quint32 line, quint32 column);
 +    Name *NAME(Name *base, const QString &id, quint32 line, quint32 column);
 +    Name *SYMBOL(Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column);
 +    Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, quint32 line, quint32 column);
 +    Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QQmlPropertyData *property, Name::Storage storage, quint32 line, quint32 column);
 +    Name *ID_OBJECT(const QString &id, const QQmlScript::Object *object, quint32 line, quint32 column);
 +    Name *ATTACH_TYPE(const QString &id, const QQmlType *attachType, Name::Storage storage, quint32 line, quint32 column);
 +
 +    Expr *UNOP(AluOp op, Expr *expr);
 +    Expr *BINOP(AluOp op, Expr *left, Expr *right);
 +    Expr *CALL(Expr *base, ExprList *args);
 +
 +    Stmt *EXP(Expr *expr);
 +    Stmt *MOVE(Expr *target, Expr *source, bool = false);
 +
 +    Stmt *JUMP(BasicBlock *target);
 +    Stmt *CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse);
 +    Stmt *RET(Expr *expr, Type type, quint32 line, quint32 column);
 +
 +    virtual void dump(QTextStream &out);
 +};
 +
 +#ifdef DEBUG_IR_STRUCTURE
 +struct IRDump : public ExprVisitor,
 +                public StmtVisitor 
 +{
 +public:
 +    IRDump();
 +
 +    void expression(QQmlJS::IR::Expr *);
 +    void basicblock(QQmlJS::IR::BasicBlock *);
 +    void statement(QQmlJS::IR::Stmt *);
 +    void function(QQmlJS::IR::Function *);
 +protected:
 +
 +    const char *indent();
 +
 +    //
 +    // expressions
 +    //
 +    virtual void visitConst(QQmlJS::IR::Const *e);
 +    virtual void visitString(QQmlJS::IR::String *e);
 +    virtual void visitName(QQmlJS::IR::Name *e);
 +    virtual void visitTemp(QQmlJS::IR::Temp *e);
 +    virtual void visitUnop(QQmlJS::IR::Unop *e);
 +    virtual void visitBinop(QQmlJS::IR::Binop *e);
 +    virtual void visitCall(QQmlJS::IR::Call *e);
 +
 +    //
 +    // statements
 +    //
 +    virtual void visitExp(QQmlJS::IR::Exp *s);
 +    virtual void visitMove(QQmlJS::IR::Move *s);
 +    virtual void visitJump(QQmlJS::IR::Jump *s);
 +    virtual void visitCJump(QQmlJS::IR::CJump *s);
 +    virtual void visitRet(QQmlJS::IR::Ret *s);
 +
 +private:
 +    int indentSize;
 +    QByteArray indentData;
 +    void inc();
 +    void dec();
 +};
 +#endif
 +
 +} // end of namespace IR
 +
 +} // end of namespace QQmlJS
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QV4IR_P_H
index 1956be8,0000000..0efb268
mode 100644,000000..100644
--- /dev/null
@@@ -1,1303 -1,0 +1,1306 @@@
-                 if (data && data->revision != 0) {
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qv4irbuilder_p.h"
 +#include "qv4compiler_p_p.h"
 +
 +#include <private/qqmlglobal_p.h>
 +#include <private/qqmlmetatype_p.h>
 +#include <private/qqmltypenamecache_p.h>
 +
 +DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
 +
 +QT_BEGIN_NAMESPACE
 +
 +using namespace QQmlJS;
 +
 +static IR::Type irTypeFromVariantType(int t, QQmlEnginePrivate *engine, const QMetaObject * /* meta */)
 +{
 +    switch (t) {
 +    case QMetaType::Bool:
 +        return IR::BoolType;
 +
 +    case QMetaType::Int:
 +        return IR::IntType;
 +
 +    case QMetaType::QReal:
 +        return IR::RealType;
 +
 +    case QMetaType::QString:
 +        return IR::StringType;
 +
 +    case QMetaType::QUrl:
 +        return IR::UrlType;
 +
++    case QMetaType::QColor:
++        return IR::ColorType;
++
 +    default:
 +        if (t == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
 +            return IR::SGAnchorLineType;
 +        } else if (engine->metaObjectForType(t)) {
 +            return IR::ObjectType;
 +        }
 +
 +        return IR::InvalidType;
 +    }
 +}
 +
 +QV4IRBuilder::QV4IRBuilder(const QV4Compiler::Expression *expr, 
 +                                                             QQmlEnginePrivate *engine)
 +: m_expression(expr), m_engine(engine), _function(0), _block(0), _discard(false)
 +{
 +}
 +
 +bool QV4IRBuilder::operator()(QQmlJS::IR::Function *function,
 +                                         QQmlJS::AST::Node *ast)
 +{
 +    bool discarded = false;
 +
 +    IR::BasicBlock *block = function->newBasicBlock();
 +
 +    qSwap(_discard, discarded);
 +    qSwap(_function, function);
 +    qSwap(_block, block);
 +
 +    ExprResult r;
 +    AST::SourceLocation location;
 +    if (AST::ExpressionNode *asExpr = ast->expressionCast()) {
 +        r = expression(asExpr);
 +        location = asExpr->firstSourceLocation();
 +    } else if (AST::Statement *asStmt = ast->statementCast()) {
 +        r = statement(asStmt);
 +        location = asStmt->firstSourceLocation();
 +    }
 +
 +    //_block->MOVE(_block->TEMP(IR::InvalidType), r.code);
 +    if (r.code) {
 +        const QMetaObject *m = 0;
 +        const IR::Type targetType = irTypeFromVariantType(m_expression->property->type, m_engine, m);
 +        if (targetType != r.type()) {
 +            IR::Expr *x = _block->TEMP(targetType);
 +            _block->MOVE(x, r, true);
 +            r.code = x;
 +        }
 +        _block->RET(r.code, targetType, location.startLine, location.startColumn);
 +    }
 +
 +    qSwap(_block, block);
 +    qSwap(_function, function);
 +    qSwap(_discard, discarded);
 +
 +    return !discarded;
 +}
 +
 +bool QV4IRBuilder::buildName(QList<QStringRef> &name,
 +                                              AST::Node *node,
 +                                              QList<AST::ExpressionNode *> *nodes)
 +{
 +    if (node->kind == AST::Node::Kind_IdentifierExpression) {
 +        name << static_cast<AST::IdentifierExpression*>(node)->name;
 +        if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node);
 +    } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
 +        AST::FieldMemberExpression *expr =
 +            static_cast<AST::FieldMemberExpression *>(node);
 +
 +        if (!buildName(name, expr->base, nodes))
 +            return false;
 +
 +        name << expr->name;
 +        if (nodes) *nodes << expr;
 +    } else {
 +        return false;
 +    }
 +
 +    return true;
 +}
 +
 +void QV4IRBuilder::discard() 
 +{ 
 +    _discard = true; 
 +}
 +
 +QV4IRBuilder::ExprResult 
 +QV4IRBuilder::expression(AST::ExpressionNode *ast)
 +{
 +    ExprResult r;
 +    if (ast) {
 +        qSwap(_expr, r);
 +        accept(ast);
 +        qSwap(_expr, r);
 +
 +        if (r.is(IR::InvalidType))
 +            discard();
 +        else {
 +            Q_ASSERT(r.hint == r.format);
 +        }
 +    }
 +
 +    return r;
 +}
 +
 +void QV4IRBuilder::condition(AST::ExpressionNode *ast, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
 +{
 +    if (! ast)
 +        return;
 +    ExprResult r(iftrue, iffalse);
 +    qSwap(_expr, r);
 +    accept(ast);
 +    qSwap(_expr, r);
 +
 +    if (r.format != ExprResult::cx) {
 +        if (! r.code)
 +            discard();
 +
 +        Q_ASSERT(r.hint == ExprResult::cx);
 +        Q_ASSERT(r.format == ExprResult::ex);
 +
 +        if (r.type() != IR::BoolType) {
 +            IR::Temp *t = _block->TEMP(IR::BoolType);
 +            _block->MOVE(t, r);
 +            r = t;
 +        }
 +
 +        _block->CJUMP(_block->UNOP(IR::OpIfTrue, r), iftrue, iffalse);
 +    }
 +}
 +
 +QV4IRBuilder::ExprResult
 +QV4IRBuilder::statement(AST::Statement *ast)
 +{
 +    ExprResult r;
 +    if (ast) {
 +        qSwap(_expr, r);
 +        accept(ast);
 +        qSwap(_expr, r);
 +
 +        if (r.is(IR::InvalidType))
 +            discard();
 +        else {
 +            Q_ASSERT(r.hint == r.format);
 +        }
 +    }
 +
 +    return r;
 +}
 +
 +void QV4IRBuilder::sourceElement(AST::SourceElement *ast)
 +{
 +    accept(ast);
 +}
 +
 +void QV4IRBuilder::implicitCvt(ExprResult &expr, IR::Type type)
 +{
 +    if (expr.type() == type)
 +        return; // nothing to do
 +
 +    IR::Expr *x = _block->TEMP(type);
 +    _block->MOVE(x, expr.code);
 +    expr.code = x;
 +}
 +
 +// QML
 +bool QV4IRBuilder::visit(AST::UiProgram *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiImportList *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiImport *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiPublicMember *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiSourceElement *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiObjectDefinition *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiObjectInitializer *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiObjectBinding *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiScriptBinding *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiArrayBinding *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiObjectMemberList *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiArrayMemberList *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UiQualifiedId *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +
 +// JS
 +bool QV4IRBuilder::visit(AST::Program *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::SourceElements *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::FunctionSourceElement *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::StatementSourceElement *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +// object literals
 +bool QV4IRBuilder::visit(AST::PropertyNameAndValueList *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::IdentifierPropertyName *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::StringLiteralPropertyName *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::NumericLiteralPropertyName *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +
 +// array literals
 +bool QV4IRBuilder::visit(AST::ElementList *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::Elision *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +
 +// function calls
 +bool QV4IRBuilder::visit(AST::ArgumentList *)
 +{
 +    Q_ASSERT(!"unreachable");
 +    return false;
 +}
 +
 +// expressions
 +bool QV4IRBuilder::visit(AST::ObjectLiteral *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::ArrayLiteral *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::ThisExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::IdentifierExpression *ast)
 +{
 +    const quint32 line = ast->identifierToken.startLine;
 +    const quint32 column = ast->identifierToken.startColumn;
 +
 +    const QString name = ast->name.toString();
 +
 +    if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) {
 +        _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value
 +    } else if (m_engine->v8engine()->illegalNames().contains(name) ) {
 +        if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name;
 +        return false;
 +    } else if (const QQmlScript::Object *obj = m_expression->ids->value(name)) {
 +        IR::Name *code = _block->ID_OBJECT(name, obj, line, column);
 +        if (obj == m_expression->component)
 +            code->storage = IR::Name::RootStorage;
 +        _expr.code = code;
 +    } else {
 +
 +        QQmlTypeNameCache::Result r = m_expression->importCache->query(name);
 +        if (r.isValid()) {
 +            if (r.type) {
 +                _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column);
 +            }
 +            // We don't support anything else
 +        } else {
 +            bool found = false;
 +
 +            if (m_expression->context != m_expression->component) {
 +                // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same
 +                QQmlPropertyCache *cache = m_expression->context->synthCache;
 +                const QMetaObject *metaObject = m_expression->context->metaObject();
 +                if (!cache) cache = m_engine->cache(metaObject);
 +
 +                QQmlPropertyData *data = cache->property(name);
 +
-                 if (data && data->revision != 0) {
++                if (data && data->hasRevision()) {
 +                    if (qmlVerboseCompiler()) 
 +                        qWarning() << "*** versioned symbol:" << name;
 +                    discard();
 +                    return false;
 +                }
 +
 +                if (data && !data->isFunction()) {
 +                    IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
 +                    _expr.code = _block->SYMBOL(irType, name, metaObject, data, IR::Name::ScopeStorage, line, column);
 +                    found = true;
 +                } 
 +            }
 +
 +            if (!found) {
 +                QQmlPropertyCache *cache = m_expression->component->synthCache;
 +                const QMetaObject *metaObject = m_expression->component->metaObject();
 +                if (!cache) cache = m_engine->cache(metaObject);
 +
 +                QQmlPropertyData *data = cache->property(name);
 +
-                 if (data->revision != 0) {
++                if (data && data->hasRevision()) {
 +                    if (qmlVerboseCompiler()) 
 +                        qWarning() << "*** versioned symbol:" << name;
 +                    discard();
 +                    return false;
 +                }
 +
 +                if (data && !data->isFunction()) {
 +                    IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
 +                    _expr.code = _block->SYMBOL(irType, name, metaObject, data, IR::Name::RootStorage, line, column);
 +                    found = true;
 +                } 
 +            }
 +
 +            if (!found && qmlVerboseCompiler())
 +                qWarning() << "*** unknown symbol:" << name;
 +        }
 +    }
 +
 +    if (_expr.code && _expr.hint == ExprResult::cx) {
 +        _expr.format = ExprResult::cx;
 +
 +        if (_expr.type() != IR::BoolType) {
 +            IR::Temp *t = _block->TEMP(IR::BoolType);
 +            _block->MOVE(t, _expr);
 +            _expr.code = t;
 +        }
 +
 +        _block->CJUMP(_expr.code, _expr.iftrue, _expr.iffalse);
 +        _expr.code = 0;
 +    }
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::NullExpression *)
 +{
 +    // ### TODO: cx format
 +    _expr.code = _block->CONST(IR::NullType, 0);
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::TrueLiteral *)
 +{
 +    // ### TODO: cx format
 +    _expr.code = _block->CONST(IR::BoolType, 1);
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::FalseLiteral *)
 +{
 +    // ### TODO: cx format
 +    _expr.code = _block->CONST(IR::BoolType, 0);
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::StringLiteral *ast)
 +{
 +    // ### TODO: cx format
 +    _expr.code = _block->STRING(ast->value);
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::NumericLiteral *ast)
 +{
 +    if (_expr.hint == ExprResult::cx) {
 +        _expr.format = ExprResult::cx;
 +        _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse);
 +    } else {
 +        _expr.code = _block->CONST(ast->value);
 +    }
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::RegExpLiteral *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::NestedExpression *)
 +{
 +    return true; // the value of the nested expression
 +}
 +
 +bool QV4IRBuilder::visit(AST::ArrayMemberExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
 +{
 +    if (IR::Expr *left = expression(ast->base)) {
 +        if (IR::Name *baseName = left->asName()) {
 +            const quint32 line = ast->identifierToken.startLine;
 +            const quint32 column = ast->identifierToken.startColumn;
 +
 +            QString name = ast->name.toString();
 +
 +            switch(baseName->symbol) {
 +            case IR::Name::Unbound:
 +                break;
 +
 +            case IR::Name::AttachType:
 +                if (name.at(0).isUpper()) {
 +                    QByteArray utf8Name = name.toUtf8();
 +                    const char *enumName = utf8Name.constData();
 +
 +                    const QMetaObject *meta = baseName->declarativeType->metaObject();
 +                    bool found = false;
 +                    for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) {
 +                        QMetaEnum e = meta->enumerator(ii);
 +                        for (int jj = 0; !found && jj < e.keyCount(); ++jj) {
 +                            if (0 == strcmp(e.key(jj), enumName)) {
 +                                found = true;
 +                                _expr.code = _block->CONST(IR::IntType, e.value(jj));
 +                            }
 +                        }
 +                    }
 +
 +                    if (!found && qmlVerboseCompiler())
 +                        qWarning() << "*** unresolved enum:" 
 +                                   << (*baseName->id + QLatin1String(".") + ast->name.toString());
 +                } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) {
 +                    QQmlPropertyCache *cache = m_engine->cache(attachedMeta);
 +                    QQmlPropertyData *data = cache->property(name);
 +
 +                    if (!data || data->isFunction())
 +                        return false; // Don't support methods (or non-existing properties ;)
 +
 +                    if(!data->isFinal()) {
 +                        if (qmlVerboseCompiler())
 +                            qWarning() << "*** non-final attached property:"
 +                                       << (*baseName->id + QLatin1String(".") + ast->name.toString());
 +                        return false; // We don't know enough about this property
 +                    }
 +
 +                    IR::Type irType = irTypeFromVariantType(data->propType, m_engine, attachedMeta);
 +                    _expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data, line, column);
 +                }
 +                break;
 +
 +            case IR::Name::IdObject: {
 +                const QQmlScript::Object *idObject = baseName->idObject;
 +                QQmlPropertyCache *cache = 
 +                    idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject());
 +
 +                QQmlPropertyData *data = cache->property(name);
 +
 +                if (!data || data->isFunction())
 +                    return false; // Don't support methods (or non-existing properties ;)
 +
++                if (data->hasRevision()) {
 +                    if (qmlVerboseCompiler()) 
 +                        qWarning() << "*** versioned symbol:" << name;
 +                    discard();
 +                    return false;
 +                }
 +
 +                IR::Type irType = irTypeFromVariantType(data->propType, m_engine, idObject->metaObject());
 +                _expr.code = _block->SYMBOL(baseName, irType, name,
 +                                            idObject->metaObject(), data, line, column);
 +                }
 +                break;
 +
 +            case IR::Name::Property: 
 +                if (baseName->type == IR::ObjectType && baseName->meta && baseName->property->isFinal()) {
 +                    QQmlPropertyCache *cache = m_engine->cache(baseName->meta);
 +                    if (!cache)
 +                        return false;
 +
 +                    if (QQmlPropertyData *data = cache->property(name)) {
 +                        if (!data->isFinal()) {
 +                            if (qmlVerboseCompiler())
 +                                qWarning() << "*** non-final property access:"
 +                                           << (*baseName->id + QLatin1String(".") + ast->name.toString());
 +                            return false; // We don't know enough about this property
 +                        }
 +
 +                        IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta);
 +                        _expr.code = _block->SYMBOL(baseName, irType, name,
 +                                                    baseName->meta, data, line, column);
 +                    }
 +                }
 +                break;
 +
 +            case IR::Name::Object: 
 +            case IR::Name::Slot:
 +                break;
 +            }
 +        }
 +    }
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::preVisit(AST::Node *)
 +{
 +    return ! _discard;
 +}
 +
 +bool QV4IRBuilder::visit(AST::NewMemberExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::NewExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::CallExpression *ast)
 +{
 +    QList<QStringRef> names;
 +    QList<AST::ExpressionNode *> nameNodes;
 +
 +    names.reserve(4);
 +    nameNodes.reserve(4);
 +
 +    if (buildName(names, ast->base, &nameNodes)) {
 +        //ExprResult base = expression(ast->base);
 +        QString id;
 +        for (int i = 0; i < names.size(); ++i) {
 +            if (! i)
 +                id += QLatin1Char('.');
 +            id += names.at(i);
 +        }
 +        const AST::SourceLocation loc = nameNodes.last()->firstSourceLocation();
 +        IR::Expr *base = _block->NAME(id, loc.startLine, loc.startColumn);
 +
 +        IR::ExprList *args = 0, **argsInserter = &args;
 +        for (AST::ArgumentList *it = ast->arguments; it; it = it->next) {
 +            IR::Expr *arg = expression(it->expression);
 +            *argsInserter = _function->pool->New<IR::ExprList>();
 +            (*argsInserter)->init(arg);
 +            argsInserter = &(*argsInserter)->next;
 +        }
 +
 +        IR::Temp *r = _block->TEMP(IR::InvalidType);
 +        IR::Expr *call = _block->CALL(base, args);
 +        _block->MOVE(r, call);
 +        r->type = call->type;
 +        _expr.code = r;
 +    }
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::PostIncrementExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::PostDecrementExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::DeleteExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::VoidExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::TypeOfExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::PreIncrementExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::PreDecrementExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UnaryPlusExpression *ast)
 +{
 +    ExprResult expr = expression(ast->expression);
 +    if (expr.isNot(IR::InvalidType)) {
 +        if (expr.code->asConst() != 0) {
 +            _expr = expr;
 +            return false;
 +        }
 +
 +        IR::Expr *code = _block->UNOP(IR::OpUPlus, expr);
 +        _expr.code = _block->TEMP(code->type);
 +        _block->MOVE(_expr, code);
 +    }
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::UnaryMinusExpression *ast)
 +{
 +    ExprResult expr = expression(ast->expression);
 +    if (expr.isNot(IR::InvalidType)) {
 +        if (IR::Const *c = expr.code->asConst()) {
 +            _expr = expr;
 +            _expr.code = _block->CONST(-c->value);
 +            return false;
 +        }
 +
 +        IR::Expr *code = _block->UNOP(IR::OpUMinus, expr);
 +        _expr.code = _block->TEMP(code->type);
 +        _block->MOVE(_expr, code);
 +    }
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::TildeExpression *ast)
 +{
 +    ExprResult expr = expression(ast->expression);
 +    if (expr.isNot(IR::InvalidType)) {
 +        if (IR::Const *c = expr.code->asConst()) {
 +            _expr = expr;
 +            _expr.code = _block->CONST(~int(c->value));
 +            return false;
 +        }
 +        IR::Expr *code = _block->UNOP(IR::OpCompl, expr);
 +        _expr.code = _block->TEMP(code->type);
 +        _block->MOVE(_expr, code);
 +    }
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::NotExpression *ast)
 +{
 +    ExprResult expr = expression(ast->expression);
 +
 +    if (expr.isNot(IR::InvalidType)) {
 +        if (IR::Const *c = expr.code->asConst()) {
 +            _expr = expr;
 +            _expr.code = _block->CONST(!c->value);
 +            return false;
 +        }
 +
 +        IR::Expr *code = _block->UNOP(IR::OpNot, expr);
 +        _expr.code = _block->TEMP(code->type);
 +        _block->MOVE(_expr, code);
 +
 +    } else if (expr.hint == ExprResult::cx) {
 +        expr.format = ExprResult::cx;
 +        _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse);
 +        return false;
 +    }
 +
 +    return false;
 +}
 +
 +void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right)
 +{
 +    if (IR::Type t = maxType(left.type(), right.type())) {
 +        implicitCvt(left, t);
 +        implicitCvt(right, t);
 +
 +        if (_expr.hint == ExprResult::cx) {
 +            _expr.format = ExprResult::cx;
 +            _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
 +        } else {
 +            IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
 +            _expr.code = _block->TEMP(code->type);
 +            _block->MOVE(_expr.code, code);
 +        }
 +    }
 +}
 +
 +bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
 +{
 +    switch (ast->op) {
 +    case QSOperator::And: {
 +        if (_expr.hint == ExprResult::cx) {
 +            _expr.format = ExprResult::cx;
 +
 +            Q_ASSERT(_expr.iffalse != 0);
 +            Q_ASSERT(_expr.iftrue != 0);
 +
 +            IR::BasicBlock *iftrue = _function->newBasicBlock();
 +            condition(ast->left, iftrue, _expr.iffalse);
 +
 +            _block = iftrue;
 +            condition(ast->right, _expr.iftrue, _expr.iffalse);
 +        } else {
 +            IR::BasicBlock *iftrue = _function->newBasicBlock();
 +            IR::BasicBlock *iffalse = _function->newBasicBlock();
 +            IR::BasicBlock *endif = _function->newBasicBlock();
 +
 +            condition(ast->left, iftrue, iffalse);
 +
 +            IR::Temp *r = _block->TEMP(IR::InvalidType);
 +
 +            _block = iffalse;
 +            _block->MOVE(r, _block->CONST(0)); // ### use the right null value
 +            _block->JUMP(endif);
 +
 +            _block = iftrue;
 +            ExprResult right = expression(ast->right);
 +            _block->MOVE(r, right);
 +            _block->JUMP(endif);
 +
 +            _block = endif;
 +
 +            r->type = right.type(); // ### not exactly, it can be IR::BoolType.
 +            _expr.code = r;
 +        }
 +    } break;
 +
 +    case QSOperator::Or: {
 +        IR::BasicBlock *iftrue = _function->newBasicBlock();
 +        IR::BasicBlock *endif = _function->newBasicBlock();
 +
 +        ExprResult left = expression(ast->left);
 +        IR::Temp *r = _block->TEMP(left.type());
 +        _block->MOVE(r, left);
 +
 +        IR::Expr *cond = r;
 +        if (r->type != IR::BoolType) {
 +            cond = _block->TEMP(IR::BoolType);
 +            _block->MOVE(cond, r);
 +        }
 +
 +        _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif);
 +
 +        _block = iftrue;
 +        ExprResult right = expression(ast->right);
 +        _block->MOVE(r, right);
 +        _block->JUMP(endif);
 +
 +        if (left.type() != right.type())
 +            discard();
 +
 +        _expr.code = r;
 +
 +        _block = endif;
 +    } break;
 +
 +    case QSOperator::Lt:
 +    case QSOperator::Gt:
 +    case QSOperator::Le:
 +    case QSOperator::Ge: {
 +        ExprResult left = expression(ast->left);
 +        ExprResult right = expression(ast->right);
 +        if (left.type() == IR::StringType && right.type() == IR::StringType) {
 +            binop(ast, left, right);
 +        } else if (left.isValid() && right.isValid()) {
 +            implicitCvt(left, IR::RealType);
 +            implicitCvt(right, IR::RealType);
 +            binop(ast, left, right);
 +        }
 +    } break;
 +
 +    case QSOperator::NotEqual:
 +    case QSOperator::Equal: {
 +        ExprResult left = expression(ast->left);
 +        ExprResult right = expression(ast->right);
 +        if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) &&
 +                (right.type() == IR::NullType || right.type() == IR::UndefinedType)) {
 +            const bool isEq = ast->op == QSOperator::Equal;
 +            if (_expr.hint == ExprResult::cx) {
 +                _expr.format = ExprResult::cx;
 +                _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
 +            } else {
 +                _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
 +            }
 +        } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) ||
 +                   (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) {
 +            implicitCvt(left, IR::RealType);
 +            implicitCvt(right, IR::RealType);
 +            binop(ast, left, right);
 +        } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) {
 +            implicitCvt(left, IR::BoolType);
 +            implicitCvt(right, IR::BoolType);
 +        } else if (left.isValid() && right.isValid()) {
 +            binop(ast, left, right);
 +        }
 +    } break;
 +
 +    case QSOperator::StrictEqual:
 +    case QSOperator::StrictNotEqual: {
 +        ExprResult left = expression(ast->left);
 +        ExprResult right = expression(ast->right);
 +        if (left.type() == right.type()) {
 +            binop(ast, left, right);
 +        } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) {
 +            // left and right have numeric type (int or real)
 +            binop(ast, left, right);
 +        } else if (left.isValid() && right.isValid()) {
 +            const bool isEq = ast->op == QSOperator::StrictEqual;
 +            if (_expr.hint == ExprResult::cx) {
 +                _expr.format = ExprResult::cx;
 +                _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
 +            } else {
 +                _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
 +            }
 +        }
 +    } break;
 +
 +    case QSOperator::BitAnd:
 +    case QSOperator::BitOr:
 +    case QSOperator::BitXor:
 +    case QSOperator::LShift:
 +    case QSOperator::RShift:
 +    case QSOperator::URShift: {
 +        ExprResult left = expression(ast->left);
 +        if (left.is(IR::InvalidType))
 +            return false;
 +
 +        ExprResult right = expression(ast->right);
 +        if (right.is(IR::InvalidType))
 +            return false;
 +
 +        implicitCvt(left, IR::IntType);
 +        implicitCvt(right, IR::IntType);
 +
 +        IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
 +        _expr.code = _block->TEMP(code->type);
 +        _block->MOVE(_expr.code, code);
 +
 +    } break;
 +
 +    case QSOperator::Add: {
 +        ExprResult left = expression(ast->left);
 +        if (left.is(IR::InvalidType))
 +            return false;
 +
 +        ExprResult right = expression(ast->right);
 +        if (right.is(IR::InvalidType))
 +            return false;
 +
 +        if (left.isPrimitive() && right.isPrimitive()) {
 +            if (left.type() == IR::StringType || right.type() == IR::StringType) {
 +                implicitCvt(left, IR::StringType);
 +                implicitCvt(right, IR::StringType);
 +            }
 +            binop(ast, left, right);
 +        }
 +    } break;
 +
 +    case QSOperator::Div:
 +    case QSOperator::Mod:
 +    case QSOperator::Mul:
 +    case QSOperator::Sub: {
 +        ExprResult left = expression(ast->left);
 +        if (left.is(IR::InvalidType))
 +            return false;
 +
 +        ExprResult right = expression(ast->right);
 +        if (right.is(IR::InvalidType))
 +            return false;
 +
 +        IR::Type t = maxType(left.type(), right.type());
 +        if (t >= IR::FirstNumberType) {
 +            implicitCvt(left, IR::RealType);
 +            implicitCvt(right, IR::RealType);
 +
 +            IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
 +            _expr.code = _block->TEMP(code->type);
 +            _block->MOVE(_expr.code, code);
 +        }
 +    } break;
 +
 +    case QSOperator::In:
 +    case QSOperator::InstanceOf:
 +    case QSOperator::Assign:
 +    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:
 +        // yup, we don't do those.
 +        break;
 +    } // switch
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::ConditionalExpression *ast)
 +{
 +    IR::BasicBlock *iftrue = _function->newBasicBlock();
 +    IR::BasicBlock *iffalse = _function->newBasicBlock();
 +    IR::BasicBlock *endif = _function->newBasicBlock();
 +
 +    condition(ast->expression, iftrue, iffalse);
 +
 +    IR::Temp *r = _block->TEMP(IR::InvalidType);
 +
 +    qSwap(_block, iftrue);
 +    ExprResult ok = expression(ast->ok);
 +    _block->MOVE(r, ok);
 +    _block->JUMP(endif);
 +    qSwap(_block, iftrue);
 +
 +    qSwap(_block, iffalse);
 +    ExprResult ko = expression(ast->ko);
 +    _block->MOVE(r, ko);
 +    _block->JUMP(endif);
 +    qSwap(_block, iffalse);
 +
 +    r->type = maxType(ok.type(), ko.type());
 +    _expr.code = r;
 +
 +    _block = endif;
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::Expression *ast)
 +{
 +    _block->EXP(expression(ast->left));
 +    _expr = expression(ast->right);
 +
 +    return false;
 +}
 +
 +
 +// statements
 +bool QV4IRBuilder::visit(AST::Block *ast)
 +{
 +    if (ast->statements && ! ast->statements->next) {
 +        // we have one and only one statement
 +        accept(ast->statements->statement);
 +    }
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::StatementList *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::VariableStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::VariableDeclarationList *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::VariableDeclaration *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::EmptyStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::ExpressionStatement *ast)
 +{
 +    if (ast->expression) {
 +         // return the value of this expression
 +        return true;
 +    }
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::IfStatement *ast)
 +{
 +    if (! ast->ko) {
 +        // This is an if statement without an else branch.
 +        discard();
 +    } else {
 +        IR::BasicBlock *iftrue = _function->newBasicBlock();
 +        IR::BasicBlock *iffalse = _function->newBasicBlock();
 +        IR::BasicBlock *endif = _function->newBasicBlock();
 +
 +        condition(ast->expression, iftrue, iffalse);
 +
 +        IR::Temp *r = _block->TEMP(IR::InvalidType);
 +
 +        qSwap(_block, iftrue);
 +        ExprResult ok = statement(ast->ok);
 +        _block->MOVE(r, ok);
 +        _block->JUMP(endif);
 +        qSwap(_block, iftrue);
 +
 +        qSwap(_block, iffalse);
 +        ExprResult ko = statement(ast->ko);
 +        _block->MOVE(r, ko);
 +        _block->JUMP(endif);
 +        qSwap(_block, iffalse);
 +
 +        r->type = maxType(ok.type(), ko.type());
 +        _expr.code = r;
 +
 +        _block = endif;
 +    }
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::DoWhileStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::WhileStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::ForStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::LocalForStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::ForEachStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::LocalForEachStatement *)
 +{
 +    discard();
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::ContinueStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::BreakStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::ReturnStatement *ast)
 +{
 +    if (ast->expression) {
 +        // return the value of the expression
 +        return true;
 +    }
 +
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::WithStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::SwitchStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::CaseBlock *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::CaseClauses *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::CaseClause *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::DefaultClause *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::LabelledStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::ThrowStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::TryStatement *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::Catch *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::Finally *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::FunctionDeclaration *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::FunctionExpression *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::FormalParameterList *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::FunctionBody *)
 +{
 +    return false;
 +}
 +
 +bool QV4IRBuilder::visit(AST::DebuggerStatement *)
 +{
 +    return false;
 +}
 +
 +QT_END_NAMESPACE
index b6b03e4,0000000..d23cc61
mode 100644,000000..100644
--- /dev/null
@@@ -1,122 -1,0 +1,123 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QV4PROGRAM_P_H
 +#define QV4PROGRAM_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 "qv4instruction_p.h"
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +struct QV4Program {
 +    quint32 bindings;
 +    quint32 dataLength;
 +    quint32 signalTableOffset;
 +    quint32 exceptionDataOffset;
 +    quint16 subscriptions;
 +    quint16 identifiers;
 +    quint16 instructionCount;
 +
 +    struct BindingReference {
 +        quint32 binding;
 +        quint32 blockMask;
 +    };
 +    
 +    struct BindingReferenceList {
 +        quint32 count;
 +        BindingReference bindings[];
 +    };
 +
 +    inline const char *data() const;
 +    inline const char *instructions() const;
 +    inline BindingReferenceList *signalTable(int signalIndex) const;
 +};
 +
 +enum QQmlRegisterType { 
 +    UndefinedType,
 +    QObjectStarType,
 +    QRealType,
 +    IntType,
 +    BoolType,
 +
 +    PODValueType,
 +
 +    FirstCleanupType, 
 +    QStringType = FirstCleanupType,
 +    QUrlType,
 +    QVariantType,
++    QColorType
 +};
 +
 +const char *QV4Program::data() const 
 +{ 
 +    return ((const char *)this) + sizeof(QV4Program); 
 +}
 +
 +const char *QV4Program::instructions() const
 +{ 
 +    return (const char *)(data() + dataLength);
 +}
 +
 +QV4Program::BindingReferenceList *QV4Program::signalTable(int signalIndex) const 
 +{ 
 +    quint32 *signalTable = (quint32 *)(data() + signalTableOffset);
 +    return (BindingReferenceList *)(signalTable + signalTable[signalIndex]);
 +}
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QV4PROGRAM_P_H
 +
index 29fef3c,0000000..d85f9aa
mode 100644,000000..100644
--- /dev/null
@@@ -1,93 -1,0 +1,111 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QJSCONVERTER_P_H
 +#define QJSCONVERTER_P_H
 +
 +#include "qjsvalue_p.h"
 +#include <QtCore/qglobal.h>
 +#include <QtCore/qnumeric.h>
 +#include <QtCore/qstring.h>
 +#include <QtCore/qstringlist.h>
 +#include <QtCore/qvarlengtharray.h>
 +#include <QtCore/qregexp.h>
 +#include <QtCore/qdatetime.h>
 +
 +#include <private/qv8_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +/*
 +  \internal
 +  \class QJSConverter
 +  QJSValue and QJSEngine helper class. This class's responsibility is to convert values
 +  between JS values and Qt/C++ values.
 +
 +  This is a nice way to inline these functions in both QJSValue and QJSEngine.
 +*/
 +class QJSConverter {
 +public:
 +    static inline quint32 toArrayIndex(const QString& string);
 +
 +    static inline QString toString(v8::Handle<v8::String> jsString);
 +    static inline v8::Local<v8::String> toString(const QString& string);
 +    static inline QString toString(double value);
 +
 +    enum {
 +        PropertyAttributeMask = v8::ReadOnly | v8::DontDelete | v8::DontEnum,
 +    };
 +    // return a mask of v8::PropertyAttribute that may also contains QScriptValue::PropertyGetter or QScriptValue::PropertySetter
 +    static inline uint toPropertyAttributes(const QFlags<QJSValuePrivate::PropertyFlag>& flags);
 +
 +    // Converts a JS RegExp to a QRegExp.
 +    // The conversion is not 100% exact since ECMA regexp and QRegExp
 +    // have different semantics/flags, but we try to do our best.
 +    static inline QRegExp toRegExp(v8::Handle<v8::RegExp> jsRegExp);
 +
 +    // Converts a QRegExp to a JS RegExp.
 +    // The conversion is not 100% exact since ECMA regexp and QRegExp
 +    // have different semantics/flags, but we try to do our best.
 +    static inline v8::Local<v8::RegExp> toRegExp(const QRegExp &re);
 +
 +    // Converts a QStringList to JS.
 +    // The result is a new Array object with length equal to the length
 +    // of the QStringList, and the elements being the QStringList's
 +    // elements converted to JS Strings.
 +    static inline v8::Local<v8::Array> toStringList(const QStringList &lst);
 +
 +    // Converts a JS Array object to a QStringList.
 +    // The result is a QStringList with length equal to the length
 +    // of the JS Array, and elements being the JS Array's elements
 +    // converted to QStrings.
 +    static inline QStringList toStringList(v8::Handle<v8::Array> jsArray);
 +
 +    // Converts a JS Date to a QDateTime.
 +    static inline QDateTime toDateTime(v8::Handle<v8::Date> jsDate);
 +
 +    // Converts a QDateTime to a JS Date.
 +    static inline v8::Local<v8::Value> toDateTime(const QDateTime &dt);
 +};
 +
 +QT_END_NAMESPACE
 +
 +#endif
index 1521c75,0000000..fa2584b
mode 100644,000000..100644
--- /dev/null
@@@ -1,141 -1,0 +1,159 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QJSENGINE_H
 +#define QJSENGINE_H
 +
 +#include <QtCore/qmetatype.h>
 +
 +#include <QtCore/qvariant.h>
 +#include <QtCore/qsharedpointer.h>
 +#include <QtCore/qobject.h>
 +#include <QtQml/qjsvalue.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class QV8Engine;
 +
 +template <typename T>
 +inline T qjsvalue_cast(const QJSValue &);
 +
 +class QJSEnginePrivate;
 +class Q_QML_EXPORT QJSEngine
 +    : public QObject
 +{
 +    Q_OBJECT
 +public:
 +#ifdef QT_DEPRECATED
 +    enum ContextOwnership {
 +        AdoptCurrentContext,
 +        CreateNewContext
 +    };
 +    QT_DEPRECATED explicit QJSEngine(ContextOwnership ownership);
 +#endif
 +
 +    QJSEngine();
 +    explicit QJSEngine(QObject *parent);
 +    virtual ~QJSEngine();
 +
 +    QJSValue globalObject() const;
 +
 +    QJSValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
 +
 +    QJSValue newObject();
 +    QJSValue newArray(uint length = 0);
 +
 +    QJSValue newQObject(QObject *object);
 +
 +    template <typename T>
 +    inline QJSValue toScriptValue(const T &value)
 +    {
 +        return create(qMetaTypeId<T>(), &value);
 +    }
 +    template <typename T>
 +    inline T fromScriptValue(const QJSValue &value)
 +    {
 +        return qjsvalue_cast<T>(value);
 +    }
 +
 +    void collectGarbage();
 +
 +    QV8Engine *handle() const { return d; }
 +
 +#ifdef QT_DEPRECATED
 +    QT_DEPRECATED bool hasUncaughtException() const;
 +    QT_DEPRECATED QJSValue uncaughtException() const;
 +    QT_DEPRECATED void clearExceptions();
 +#endif
 +
 +Q_SIGNALS:
 +    void signalHandlerException(const QJSValue &exception);
 +
 +private:
 +    QJSValue create(int type, const void *ptr);
 +
 +    static bool convertV2(const QJSValue &value, int type, void *ptr);
 +
 +    friend inline bool qjsvalue_cast_helper(const QJSValue &, int, void *);
 +
 +protected:
 +    QJSEngine(QJSEnginePrivate &dd, QObject *parent = 0);
 +
 +private:
 +    QV8Engine *d;
 +    Q_DISABLE_COPY(QJSEngine)
 +    Q_DECLARE_PRIVATE(QJSEngine)
 +    friend class QV8Engine;
 +};
 +
 +inline bool qjsvalue_cast_helper(const QJSValue &value, int type, void *ptr)
 +{
 +    return QJSEngine::convertV2(value, type, ptr);
 +}
 +
 +template<typename T>
 +T qjsvalue_cast(const QJSValue &value)
 +{
 +    T t;
 +    const int id = qMetaTypeId<T>();
 +
 +    if (qjsvalue_cast_helper(value, id, &t))
 +        return t;
 +    else if (value.isVariant())
 +        return qvariant_cast<T>(value.toVariant());
 +
 +    return T();
 +}
 +
 +template <>
 +inline QVariant qjsvalue_cast<QVariant>(const QJSValue &value)
 +{
 +    return value.toVariant();
 +}
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QJSENGINE_H
index ecd5f7c,0000000..9866aa8
mode 100644,000000..100644
--- /dev/null
@@@ -1,57 -1,0 +1,75 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QJSENGINE_P_H
 +#define QJSENGINE_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/private/qobject_p.h>
 +#include "qjsengine.h"
 +
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class QJSEnginePrivate : public QObjectPrivate
 +{
 +    Q_DECLARE_PUBLIC(QJSEngine)
 +
 +public:
 +    static QJSEnginePrivate* get(QJSEngine*e) { return e->d_func(); }
 +
 +    QJSEnginePrivate() {}
 +};
 +
 +QT_END_NAMESPACE
 +
 +#endif // QJSENGINE_P_H
index 30ea2e7,0000000..209090e
mode 100644,000000..100644
--- /dev/null
@@@ -1,143 -1,0 +1,160 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
- ** If you have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QJSVALUE_H
 +#define QJSVALUE_H
 +
 +#include <QtQml/qtqmlglobal.h>
-     QT_ASCII_CAST_WARN_CONSTRUCTOR QJSValue(const char *str);
 +#include <QtCore/qstring.h>
 +#include <QtCore/qlist.h>
 +#include <QtCore/qsharedpointer.h>
 +#include <QtCore/qshareddata.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class QJSValue;
 +class QJSEngine;
 +class QVariant;
 +class QObject;
 +struct QMetaObject;
 +class QDateTime;
 +
 +typedef QList<QJSValue> QJSValueList;
 +
 +class QJSValuePrivate;
 +struct QScriptValuePrivatePointerDeleter;
 +template <class T> class QScriptPassPointer;
 +
 +class Q_QML_EXPORT QJSValue
 +{
 +public:
 +    enum SpecialValue {
 +        NullValue,
 +        UndefinedValue
 +    };
 +
 +public:
 +    QJSValue(SpecialValue value = UndefinedValue);
 +    ~QJSValue();
 +    QJSValue(const QJSValue &other);
 +
 +    QJSValue(bool value);
 +    QJSValue(int value);
 +    QJSValue(uint value);
 +    QJSValue(double value);
 +    QJSValue(const QString &value);
 +    QJSValue(const QLatin1String &value);
 +#ifndef QT_NO_CAST_FROM_ASCII
++    QT_ASCII_CAST_WARN QJSValue(const char *str);
 +#endif
 +
 +    QJSValue &operator=(const QJSValue &other);
 +
 +    bool isBool() const;
 +    bool isNumber() const;
 +    bool isNull() const;
 +    bool isString() const;
 +    bool isUndefined() const;
 +    bool isVariant() const;
 +    bool isQObject() const;
 +    bool isObject() const;
 +    bool isDate() const;
 +    bool isRegExp() const;
 +    bool isArray() const;
 +    bool isError() const;
 +
 +    QString toString() const;
 +    double toNumber() const;
 +    qint32 toInt() const;
 +    quint32 toUInt() const;
 +    bool toBool() const;
 +    QVariant toVariant() const;
 +    QObject *toQObject() const;
 +    QDateTime toDateTime() const;
 +
 +    bool equals(const QJSValue &other) const;
 +    bool strictlyEquals(const QJSValue &other) const;
 +
 +    QJSValue prototype() const;
 +    void setPrototype(const QJSValue &prototype);
 +
 +    QJSValue property(const QString &name) const;
 +    void setProperty(const QString &name, const QJSValue &value);
 +
 +    bool hasProperty(const QString &name) const;
 +    bool hasOwnProperty(const QString &name) const;
 +
 +    QJSValue property(quint32 arrayIndex) const;
 +    void setProperty(quint32 arrayIndex, const QJSValue &value);
 +
 +    bool deleteProperty(const QString &name);
 +
 +    bool isCallable() const;
 +    QJSValue call(const QJSValueList &args = QJSValueList());
 +    QJSValue callWithInstance(const QJSValue &instance, const QJSValueList &args = QJSValueList());
 +    QJSValue callAsConstructor(const QJSValueList &args = QJSValueList());
 +
 +#ifdef QT_DEPRECATED
 +    QT_DEPRECATED QJSEngine *engine() const;
 +#endif
 +
 +private:
 +    // force compile error, prevent QJSValue(bool) to be called
 +
 +    QJSValue(void *) Q_DECL_EQ_DELETE;
 +
 +    QJSValue(QJSValuePrivate*);
 +    QJSValue(QScriptPassPointer<QJSValuePrivate>);
 +
 +private:
 +    QExplicitlySharedDataPointer<QJSValuePrivate> d_ptr;
 +
 +    Q_DECLARE_PRIVATE(QJSValue)
 +};
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif
index cd33859,0000000..fbddcfa
mode 100644,000000..100644
--- /dev/null
@@@ -1,977 -1,0 +1,995 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $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.
 +//
 +
 +#ifndef QJSVALUE_IMPL_P_H
 +#define QJSVALUE_IMPL_P_H
 +
 +#include "qjsconverter_p.h"
 +#include "qjsvalue_p.h"
 +#include "qv8engine_p.h"
 +#include "qscriptisolate_p.h"
 +
 +QT_BEGIN_NAMESPACE
 +
 +QJSValuePrivate* QJSValuePrivate::get(const QJSValue& q) { Q_ASSERT(q.d_ptr.data()); return q.d_ptr.data(); }
 +
 +QJSValue QJSValuePrivate::get(const QJSValuePrivate* d)
 +{
 +    Q_ASSERT(d);
 +    return QJSValue(const_cast<QJSValuePrivate*>(d));
 +}
 +
 +QJSValue QJSValuePrivate::get(QScriptPassPointer<QJSValuePrivate> d)
 +{
 +    Q_ASSERT(d);
 +    return QJSValue(d);
 +}
 +
 +QJSValue QJSValuePrivate::get(QJSValuePrivate* d)
 +{
 +    Q_ASSERT(d);
 +    return QJSValue(d);
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(bool value)
 +    : m_engine(0), m_state(CBool), u(value)
 +{
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(int value)
 +    : m_engine(0), m_state(CNumber), u(value)
 +{
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(uint value)
 +    : m_engine(0), m_state(CNumber), u(value)
 +{
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(double value)
 +    : m_engine(0), m_state(CNumber), u(value)
 +{
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(const QString& value)
 +    : m_engine(0), m_state(CString), u(new QString(value))
 +{
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(QJSValue::SpecialValue value)
 +    : m_engine(0), m_state(value == QJSValue::NullValue ? CNull : CUndefined)
 +{
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, bool value)
 +    : m_engine(engine), m_state(JSValue)
 +{
 +    Q_ASSERT(engine);
 +    v8::HandleScope handleScope;
 +    m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
 +    m_engine->registerValue(this);
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, int value)
 +    : m_engine(engine), m_state(JSValue)
 +{
 +    Q_ASSERT(engine);
 +    v8::HandleScope handleScope;
 +    m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
 +    m_engine->registerValue(this);
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, uint value)
 +    : m_engine(engine), m_state(JSValue)
 +{
 +    Q_ASSERT(engine);
 +    v8::HandleScope handleScope;
 +    m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
 +    m_engine->registerValue(this);
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, double value)
 +    : m_engine(engine), m_state(JSValue)
 +{
 +    Q_ASSERT(engine);
 +    v8::HandleScope handleScope;
 +    m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
 +    m_engine->registerValue(this);
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, const QString& value)
 +    : m_engine(engine), m_state(JSValue)
 +{
 +    Q_ASSERT(engine);
 +    v8::HandleScope handleScope;
 +    m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
 +    m_engine->registerValue(this);
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, QJSValue::SpecialValue value)
 +    : m_engine(engine), m_state(JSValue)
 +{
 +    Q_ASSERT(engine);
 +    v8::HandleScope handleScope;
 +    m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value));
 +    m_engine->registerValue(this);
 +}
 +
 +QJSValuePrivate::QJSValuePrivate(QV8Engine *engine, v8::Handle<v8::Value> value)
 +    : m_engine(engine), m_state(JSValue), m_value(v8::Persistent<v8::Value>::New(value))
 +{
 +    Q_ASSERT(engine);
 +    // It shouldn't happen, v8 shows errors by returning an empty handler. This is important debug
 +    // information and it can't be simply ignored.
 +    Q_ASSERT(!value.IsEmpty());
 +    m_engine->registerValue(this);
 +}
 +
 +QJSValuePrivate::~QJSValuePrivate()
 +{
 +    if (isJSBased()) {
 +        m_engine->unregisterValue(this);
 +        QScriptIsolate api(m_engine);
 +        m_value.Dispose();
 +    } else if (isStringBased()) {
 +        delete u.m_string;
 +    }
 +}
 +
 +bool QJSValuePrivate::toBool() const
 +{
 +    switch (m_state) {
 +    case JSValue:
 +        {
 +            v8::HandleScope scope;
 +            return m_value->ToBoolean()->Value();
 +        }
 +    case CNumber:
 +        return !(qIsNaN(u.m_number) || !u.m_number);
 +    case CBool:
 +        return u.m_bool;
 +    case CNull:
 +    case CUndefined:
 +        return false;
 +    case CString:
 +        return u.m_string->length();
 +    }
 +
 +    Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement.");
 +    return false; // Avoid compiler warning.
 +}
 +
 +double QJSValuePrivate::toNumber() const
 +{
 +    switch (m_state) {
 +    case JSValue:
 +    {
 +        v8::HandleScope scope;
 +        return m_value->ToNumber()->Value();
 +    }
 +    case CNumber:
 +        return u.m_number;
 +    case CBool:
 +        return u.m_bool ? 1 : 0;
 +    case CNull:
 +    case CUndefined:
 +        return qQNaN();
 +    case CString:
 +        bool ok;
 +        double result = u.m_string->toDouble(&ok);
 +        if (ok)
 +            return result;
 +        result = u.m_string->toInt(&ok, 0); // Try other bases.
 +        if (ok)
 +            return result;
 +        if (*u.m_string == QLatin1String("Infinity"))
 +            return qInf();
 +        if (*u.m_string == QLatin1String("-Infinity"))
 +            return -qInf();
 +        return u.m_string->length() ? qQNaN() : 0;
 +    }
 +
 +    Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement.");
 +    return 0; // Avoid compiler warning.
 +}
 +
 +QString QJSValuePrivate::toString() const
 +{
 +    switch (m_state) {
 +    case CBool:
 +        return u.m_bool ? QString::fromLatin1("true") : QString::fromLatin1("false");
 +    case CString:
 +        return *u.m_string;
 +    case CNumber:
 +        return QJSConverter::toString(u.m_number);
 +    case CNull:
 +        return QString::fromLatin1("null");
 +    case CUndefined:
 +        return QString::fromLatin1("undefined");
 +    case JSValue:
 +        Q_ASSERT(!m_value.IsEmpty());
 +        v8::HandleScope handleScope;
 +        v8::TryCatch tryCatch;
 +        v8::Local<v8::String> result = m_value->ToString();
 +        if (result.IsEmpty()) {
 +            result = tryCatch.Exception()->ToString();
 +            m_engine->setException(tryCatch.Exception(), tryCatch.Message());
 +        }
 +        return QJSConverter::toString(result);
 +    }
 +
 +    Q_ASSERT_X(false, "toString()", "Not all states are included in the previous switch statement.");
 +    return QString(); // Avoid compiler warning.
 +}
 +
 +QVariant QJSValuePrivate::toVariant() const
 +{
 +    switch (m_state) {
 +        case CBool:
 +            return QVariant(u.m_bool);
 +        case CString:
 +            return QVariant(*u.m_string);
 +        case CNumber:
 +            return QVariant(u.m_number);
 +        case CNull:
 +            return QVariant();
 +        case CUndefined:
 +            return QVariant();
 +        case JSValue:
 +            break;
 +    }
 +
 +    Q_ASSERT(m_state == JSValue);
 +    Q_ASSERT(!m_value.IsEmpty());
 +    Q_ASSERT(m_engine);
 +
 +    v8::HandleScope handleScope;
 +    return m_engine->variantFromJS(m_value);
 +}
 +
 +inline QDateTime QJSValuePrivate::toDataTime() const
 +{
 +    if (!isDate())
 +        return QDateTime();
 +
 +    v8::HandleScope handleScope;
 +    return QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(m_value));
 +
 +}
 +
 +QObject* QJSValuePrivate::toQObject() const
 +{
 +    if (!isJSBased())
 +        return 0;
 +
 +    v8::HandleScope handleScope;
 +    return engine()->qtObjectFromJS(m_value);
 +}
 +
 +double QJSValuePrivate::toInteger() const
 +{
 +    double result = toNumber();
 +    if (qIsNaN(result))
 +        return 0;
 +    if (qIsInf(result))
 +        return result;
 +
 +    // Must use floor explicitly rather than qFloor here. On some
 +    // platforms qFloor will cast the value to a single precision float and use
 +    // floorf() which results in test failures.
 +    return (result > 0) ? floor(result) : -1 * floor(-result);
 +}
 +
 +qint32 QJSValuePrivate::toInt32() const
 +{
 +    double result = toInteger();
 +    // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but
 +    // some of these operation are invoked in toInteger subcall.
 +    if (qIsInf(result))
 +        return 0;
 +    return result;
 +}
 +
 +quint32 QJSValuePrivate::toUInt32() const
 +{
 +    double result = toInteger();
 +    // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but
 +    // some of these operation are invoked in toInteger subcall.
 +    if (qIsInf(result))
 +        return 0;
 +
 +    // The explicit casts are required to avoid undefined behaviour. For example, casting
 +    // a negative double directly to an unsigned int on ARM NEON FPU results in the value
 +    // being set to zero. Casting to a signed int first ensures well defined behaviour.
 +    return (quint32) (qint32) result;
 +}
 +
 +quint16 QJSValuePrivate::toUInt16() const
 +{
 +    return toInt32();
 +}
 +
 +inline bool QJSValuePrivate::isArray() const
 +{
 +    return isJSBased() && m_value->IsArray();
 +}
 +
 +inline bool QJSValuePrivate::isBool() const
 +{
 +    return m_state == CBool || (isJSBased() && m_value->IsBoolean());
 +}
 +
 +inline bool QJSValuePrivate::isCallable() const
 +{
 +    if (isFunction())
 +        return true;
 +    if (isObject()) {
 +        // Our C++ wrappers register function handlers but not always act as callables.
 +        return v8::Object::Cast(*m_value)->IsCallable();
 +    }
 +    return false;
 +}
 +
 +inline bool QJSValuePrivate::isError() const
 +{
 +    if (!isJSBased())
 +        return false;
 +    v8::HandleScope handleScope;
 +    return m_value->IsError();
 +}
 +
 +inline bool QJSValuePrivate::isFunction() const
 +{
 +    return isJSBased() && m_value->IsFunction();
 +}
 +
 +inline bool QJSValuePrivate::isNull() const
 +{
 +    return m_state == CNull || (isJSBased() && m_value->IsNull());
 +}
 +
 +inline bool QJSValuePrivate::isNumber() const
 +{
 +    return m_state == CNumber || (isJSBased() && m_value->IsNumber());
 +}
 +
 +inline bool QJSValuePrivate::isObject() const
 +{
 +    return isJSBased() && m_value->IsObject();
 +}
 +
 +inline bool QJSValuePrivate::isString() const
 +{
 +    return m_state == CString || (isJSBased() && m_value->IsString());
 +}
 +
 +inline bool QJSValuePrivate::isUndefined() const
 +{
 +    return m_state == CUndefined || (isJSBased() && m_value->IsUndefined());
 +}
 +
 +inline bool QJSValuePrivate::isVariant() const
 +{
 +    return isJSBased() && m_engine->isVariant(m_value);
 +}
 +
 +bool QJSValuePrivate::isDate() const
 +{
 +    return (isJSBased() && m_value->IsDate());
 +}
 +
 +bool QJSValuePrivate::isRegExp() const
 +{
 +    return (isJSBased() && m_value->IsRegExp());
 +}
 +
 +bool QJSValuePrivate::isQObject() const
 +{
 +    return isJSBased() && engine()->isQObject(m_value);
 +}
 +
 +inline bool QJSValuePrivate::equals(QJSValuePrivate* other)
 +{
 +    if (!isJSBased() && !other->isJSBased()) {
 +        switch (m_state) {
 +        case CNull:
 +        case CUndefined:
 +            return other->isUndefined() || other->isNull();
 +        case CNumber:
 +            switch (other->m_state) {
 +            case CBool:
 +            case CString:
 +                return u.m_number == other->toNumber();
 +            case CNumber:
 +                return u.m_number == other->u.m_number;
 +            default:
 +                return false;
 +            }
 +        case CBool:
 +            switch (other->m_state) {
 +            case CBool:
 +                return u.m_bool == other->u.m_bool;
 +            case CNumber:
 +                return toNumber() == other->u.m_number;
 +            case CString:
 +                return toNumber() == other->toNumber();
 +            default:
 +                return false;
 +            }
 +        case CString:
 +            switch (other->m_state) {
 +            case CBool:
 +                return toNumber() == other->toNumber();
 +            case CNumber:
 +                return toNumber() == other->u.m_number;
 +            case CString:
 +                return *u.m_string == *other->u.m_string;
 +            default:
 +                return false;
 +            }
 +        default:
 +            Q_ASSERT_X(false, "QJSValue::equals", "Not all states are included in the previous switch statement.");
 +        }
 +    }
 +
 +    v8::HandleScope handleScope;
 +    if (isJSBased() && !other->isJSBased()) {
 +        if (!other->assignEngine(engine())) {
 +            qWarning("QJSValue::equals: cannot compare to a value created in a different engine");
 +            return false;
 +        }
 +    } else if (!isJSBased() && other->isJSBased()) {
 +        if (!assignEngine(other->engine())) {
 +            qWarning("QJSValue::equals: cannot compare to a value created in a different engine");
 +            return false;
 +        }
 +    }
 +
 +    Q_ASSERT(this->engine() && other->engine());
 +    if (this->engine() != other->engine()) {
 +        qWarning("QJSValue::equals: cannot compare to a value created in a different engine");
 +        return false;
 +    }
 +    return m_value->Equals(other->m_value);
 +}
 +
 +inline bool QJSValuePrivate::strictlyEquals(QJSValuePrivate* other)
 +{
 +    if (isJSBased()) {
 +        // We can't compare these two values without binding to the same engine.
 +        if (!other->isJSBased()) {
 +            if (other->assignEngine(engine()))
 +                return m_value->StrictEquals(other->m_value);
 +            return false;
 +        }
 +        if (other->engine() != engine()) {
 +            qWarning("QJSValue::strictlyEquals: cannot compare to a value created in a different engine");
 +            return false;
 +        }
 +        return m_value->StrictEquals(other->m_value);
 +    }
 +    if (isStringBased()) {
 +        if (other->isStringBased())
 +            return *u.m_string == *(other->u.m_string);
 +        if (other->isJSBased()) {
 +            assignEngine(other->engine());
 +            return m_value->StrictEquals(other->m_value);
 +        }
 +    }
 +    if (isNumberBased()) {
 +        if (other->isJSBased()) {
 +            assignEngine(other->engine());
 +            return m_value->StrictEquals(other->m_value);
 +        }
 +        if (m_state != other->m_state)
 +            return false;
 +        if (m_state == CNumber)
 +            return u.m_number == other->u.m_number;
 +        Q_ASSERT(m_state == CBool);
 +        return u.m_bool == other->u.m_bool;
 +    }
 +
 +    return (isUndefined() && other->isUndefined())
 +            || (isNull() && other->isNull());
 +}
 +
 +inline bool QJSValuePrivate::lessThan(QJSValuePrivate *other) const
 +{
 +    if (engine() != other->engine() && engine() && other->engine()) {
 +        qWarning("QJSValue::lessThan: cannot compare to a value created in a different engine");
 +        return false;
 +    }
 +
 +    if (isString() && other->isString())
 +        return toString() < other->toString();
 +
 +    if (isObject() || other->isObject()) {
 +        v8::HandleScope handleScope;
 +        QV8Engine *eng = m_engine ? engine() : other->engine();
 +        // FIXME: lessThan can throw an exception which will be dropped by this code:
 +        Q_ASSERT(eng);
 +        eng->saveException();
 +        QScriptSharedDataPointer<QJSValuePrivate> cmp(eng->evaluate(QString::fromLatin1("(function(a,b){return a<b})")));
 +        Q_ASSERT(cmp->isFunction());
 +        v8::Handle<v8::Value> args[2];
 +        cmp->prepareArgumentsForCall(args, QJSValueList() << QJSValuePrivate::get(this) << QJSValuePrivate::get(other));
 +        QScriptSharedDataPointer<QJSValuePrivate> resultValue(cmp->call(0, 2, args));
 +        bool result = resultValue->toBool();
 +        eng->restoreException();
 +        return result;
 +    }
 +
 +    double nthis = toNumber();
 +    double nother = other->toNumber();
 +    if (qIsNaN(nthis) || qIsNaN(nother)) {
 +        // Should return undefined in ECMA standard.
 +        return false;
 +    }
 +    return nthis < nother;
 +}
 +
 +inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::prototype() const
 +{
 +    if (isObject()) {
 +        v8::HandleScope handleScope;
 +        return new QJSValuePrivate(engine(), v8::Handle<v8::Object>::Cast(m_value)->GetPrototype());
 +    }
 +    return new QJSValuePrivate();
 +}
 +
 +inline void QJSValuePrivate::setPrototype(QJSValuePrivate* prototype)
 +{
 +    if (isObject() && (prototype->isObject() || prototype->isNull())) {
 +        if (engine() != prototype->engine()) {
 +            if (prototype->engine()) {
 +                qWarning("QJSValue::setPrototype() failed: cannot set a prototype created in a different engine");
 +                return;
 +            }
 +            prototype->assignEngine(engine());
 +        }
 +        v8::HandleScope handleScope;
 +        if (!v8::Handle<v8::Object>::Cast(m_value)->SetPrototype(*prototype))
 +            qWarning("QJSValue::setPrototype() failed: cyclic prototype value");
 +    }
 +}
 +
 +inline void QJSValuePrivate::setProperty(const QString& name, QJSValuePrivate* value, uint attribs)
 +{
 +    if (!isObject())
 +        return;
 +    v8::HandleScope handleScope;
 +    setProperty(QJSConverter::toString(name), value, attribs);
 +}
 +
 +inline void QJSValuePrivate::setProperty(v8::Handle<v8::String> name, QJSValuePrivate* value, uint attribs)
 +{
 +    if (!isObject())
 +        return;
 +
 +    if (!value->isJSBased())
 +        value->assignEngine(engine());
 +
 +    if (engine() != value->engine()) {
 +        qWarning("QJSValue::setProperty(%s) failed: "
 +                 "cannot set value created in a different engine",
 +                 qPrintable(QJSConverter::toString(name)));
 +        return;
 +    }
 +
 +    v8::TryCatch tryCatch;
 +//    if (attribs & (QJSValue::PropertyGetter | QJSValue::PropertySetter)) {
 +//        engine()->originalGlobalObject()->defineGetterOrSetter(*this, name, value->m_value, attribs);
 +//    } else {
 +        v8::Object::Cast(*m_value)->Set(name, value->m_value, v8::PropertyAttribute(attribs & QJSConverter::PropertyAttributeMask));
 +//    }
 +    if (tryCatch.HasCaught())
 +        engine()->setException(tryCatch.Exception(), tryCatch.Message());
 +}
 +
 +inline void QJSValuePrivate::setProperty(quint32 index, QJSValuePrivate* value, uint attribs)
 +{
 +    // FIXME this method should by integrated with other overloads to use the same code patch.
 +    // for now it is not possible as v8 doesn't allow to set property attributes using index based api.
 +
 +    if (!isObject())
 +        return;
 +
 +    if (attribs) {
 +        // FIXME we dont need to convert index to a string.
 +        //Object::Set(int,value) do not take attributes.
 +        setProperty(QString::number(index), value, attribs);
 +        return;
 +    }
 +
 +    if (!value->isJSBased())
 +        value->assignEngine(engine());
 +
 +    if (engine() != value->engine()) {
 +        qWarning("QJSValue::setProperty() failed: cannot set value created in a different engine");
 +        return;
 +    }
 +
 +    v8::HandleScope handleScope;
 +    v8::TryCatch tryCatch;
 +    v8::Object::Cast(*m_value)->Set(index, value->m_value);
 +    if (tryCatch.HasCaught())
 +        engine()->setException(tryCatch.Exception(), tryCatch.Message());
 +}
 +
 +inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(const QString& name) const
 +{
 +    if (!isObject())
 +        return new QJSValuePrivate();
 +    if (!name.length())
 +        return new QJSValuePrivate(engine());
 +
 +    v8::HandleScope handleScope;
 +    return property(QJSConverter::toString(name));
 +}
 +
 +inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(v8::Handle<v8::String> name) const
 +{
 +    Q_ASSERT(!name.IsEmpty());
 +    if (!isObject())
 +        return new QJSValuePrivate();
 +    return property<>(name);
 +}
 +
 +inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(quint32 index) const
 +{
 +    if (!isObject())
 +        return new QJSValuePrivate();
 +    return property<>(index);
 +}
 +
 +template<typename T>
 +inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(T name) const
 +{
 +    Q_ASSERT(isObject());
 +    v8::HandleScope handleScope;
 +    v8::Handle<v8::Object> self(v8::Object::Cast(*m_value));
 +
 +    v8::TryCatch tryCatch;
 +    v8::Handle<v8::Value> result = self->Get(name);
 +    if (tryCatch.HasCaught()) {
 +        result = tryCatch.Exception();
 +        engine()->setException(result, tryCatch.Message());
 +        return new QJSValuePrivate(engine(), result);
 +    }
 +    if (result.IsEmpty())
 +        return new QJSValuePrivate(engine());
 +    return new QJSValuePrivate(engine(), result);
 +}
 +
 +inline bool QJSValuePrivate::deleteProperty(const QString& name)
 +{
 +    if (!isObject())
 +        return false;
 +
 +    v8::HandleScope handleScope;
 +    v8::Handle<v8::Object> self(v8::Handle<v8::Object>::Cast(m_value));
 +    return self->Delete(QJSConverter::toString(name));
 +}
 +
 +inline bool QJSValuePrivate::hasProperty(const QString &name) const
 +{
 +    if (!isObject())
 +        return false;
 +
 +    v8::HandleScope handleScope;
 +    v8::Handle<v8::Object> self(v8::Handle<v8::Object>::Cast(m_value));
 +    return self->Has(QJSConverter::toString(name));
 +}
 +
 +inline bool QJSValuePrivate::hasOwnProperty(const QString &name) const
 +{
 +    if (!isObject())
 +        return false;
 +
 +    v8::HandleScope handleScope;
 +    v8::Handle<v8::Object> self(v8::Handle<v8::Object>::Cast(m_value));
 +    return self->HasOwnProperty(QJSConverter::toString(name));
 +}
 +
 +inline QJSValuePrivate::PropertyFlags QJSValuePrivate::propertyFlags(const QString& name) const
 +{
 +    if (!isObject())
 +        return QJSValuePrivate::PropertyFlags(0);
 +
 +    v8::HandleScope handleScope;
 +    return engine()->getPropertyFlags(v8::Handle<v8::Object>::Cast(m_value), QJSConverter::toString(name));
 +}
 +
 +inline QJSValuePrivate::PropertyFlags QJSValuePrivate::propertyFlags(v8::Handle<v8::String> name) const
 +{
 +    if (!isObject())
 +        return QJSValuePrivate::PropertyFlags(0);
 +
 +    v8::HandleScope handleScope;
 +    return engine()->getPropertyFlags(v8::Handle<v8::Object>::Cast(m_value), name);
 +}
 +
 +inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::call(QJSValuePrivate* thisObject, const QJSValueList& args)
 +{
 +    if (!isCallable())
 +        return new QJSValuePrivate();
 +
 +    v8::HandleScope handleScope;
 +
 +    // Convert all arguments and bind to the engine.
 +    int argc = args.size();
 +    QVarLengthArray<v8::Handle<v8::Value>, 8> argv(argc);
 +    if (!prepareArgumentsForCall(argv.data(), args)) {
 +        qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
 +        return new QJSValuePrivate(engine());
 +    }
 +
 +    return call(thisObject, argc, argv.data());
 +}
 +
 +QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::call(QJSValuePrivate* thisObject, int argc, v8::Handle<v8::Value> *argv)
 +{
 +    QV8Engine *e = engine();
 +
 +    v8::Handle<v8::Object> recv;
 +
 +    if (!thisObject || !thisObject->isObject()) {
 +        recv = v8::Handle<v8::Object>(v8::Object::Cast(*e->global()));
 +    } else {
 +        if (!thisObject->assignEngine(e)) {
 +            qWarning("QJSValue::call() failed: cannot call function with thisObject created in a different engine");
 +            return new QJSValuePrivate(engine());
 +        }
 +
 +        recv = v8::Handle<v8::Object>(v8::Object::Cast(*thisObject->m_value));
 +    }
 +
 +    if (argc < 0) {
 +        v8::Local<v8::Value> exeption = v8::Exception::TypeError(v8::String::New("Arguments must be an array"));
 +        e->setException(exeption);
 +        return new QJSValuePrivate(e, exeption);
 +    }
 +
 +    v8::TryCatch tryCatch;
 +    v8::Handle<v8::Value> result = v8::Object::Cast(*m_value)->CallAsFunction(recv, argc, argv);
 +
 +    if (result.IsEmpty()) {
 +        result = tryCatch.Exception();
 +        // TODO: figure out why v8 doesn't always produce an exception value.
 +        //Q_ASSERT(!result.IsEmpty());
 +        if (result.IsEmpty())
 +            result = v8::Exception::Error(v8::String::New("missing exception value"));
 +        e->setException(result, tryCatch.Message());
 +    }
 +
 +    return new QJSValuePrivate(e, result);
 +}
 +
 +inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::callAsConstructor(int argc, v8::Handle<v8::Value> *argv)
 +{
 +    QV8Engine *e = engine();
 +
 +    if (argc < 0) {
 +        v8::Local<v8::Value> exeption = v8::Exception::TypeError(v8::String::New("Arguments must be an array"));
 +        e->setException(exeption);
 +        return new QJSValuePrivate(e, exeption);
 +    }
 +
 +    v8::TryCatch tryCatch;
 +    v8::Handle<v8::Value> result = v8::Object::Cast(*m_value)->CallAsConstructor(argc, argv);
 +
 +    if (result.IsEmpty()) {
 +        result = tryCatch.Exception();
 +        e->setException(result, tryCatch.Message());
 +    }
 +
 +    return new QJSValuePrivate(e, result);
 +}
 +
 +inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::callAsConstructor(const QJSValueList& args)
 +{
 +    if (!isCallable())
 +        return new QJSValuePrivate();
 +
 +    v8::HandleScope handleScope;
 +
 +    // Convert all arguments and bind to the engine.
 +    int argc = args.size();
 +    QVarLengthArray<v8::Handle<v8::Value>, 8> argv(argc);
 +    if (!prepareArgumentsForCall(argv.data(), args)) {
 +        qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine");
 +        return new QJSValuePrivate(engine());
 +    }
 +
 +    return callAsConstructor(argc, argv.data());
 +}
 +
 +/*! \internal
 + * Make sure this value is associated with a v8 value belonging to this engine.
 + * If the value belongs to another engine, returns false.
 + */
 +bool QJSValuePrivate::assignEngine(QV8Engine* engine)
 +{
 +    Q_ASSERT(engine);
 +    v8::HandleScope handleScope;
 +    switch (m_state) {
 +    case CBool:
 +        m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(u.m_bool));
 +        break;
 +    case CString:
 +        m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(*u.m_string));
 +        delete u.m_string;
 +        break;
 +    case CNumber:
 +        m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(u.m_number));
 +        break;
 +    case CNull:
 +        m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(QJSValue::NullValue));
 +        break;
 +    case CUndefined:
 +        m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(QJSValue::UndefinedValue));
 +        break;
 +    default:
 +        if (this->engine() == engine)
 +            return true;
 +        else if (!isJSBased())
 +            Q_ASSERT_X(!isJSBased(), "assignEngine()", "Not all states are included in the previous switch statement.");
 +        else
 +            qWarning("JSValue can't be rassigned to an another engine.");
 +        return false;
 +    }
 +    m_engine = engine;
 +    m_state = JSValue;
 +
 +    m_engine->registerValue(this);
 +    return true;
 +}
 +
 +/*!
 +  \internal
 +  Invalidates this value (makes it undefined).
 +
 +  Does not remove the value from the engine's list of
 +  registered values; that's the responsibility of the caller.
 +*/
 +void QJSValuePrivate::invalidate()
 +{
 +    if (isJSBased()) {
 +        m_value.Dispose();
 +        m_value.Clear();
 +    } else if (isStringBased()) {
 +        delete u.m_string;
 +    }
 +    m_engine = 0;
 +    m_state = CUndefined;
 +}
 +
 +QV8Engine* QJSValuePrivate::engine() const
 +{
 +    return m_engine;
 +}
 +
 +inline QJSValuePrivate::operator v8::Handle<v8::Value>() const
 +{
 +    Q_ASSERT(isJSBased());
 +    return m_value;
 +}
 +
 +inline QJSValuePrivate::operator v8::Handle<v8::Object>() const
 +{
 +    Q_ASSERT(isObject());
 +    return v8::Handle<v8::Object>::Cast(m_value);
 +}
 +
 +/*!
 + * Return a v8::Handle, assign to the engine if needed.
 + */
 +v8::Handle<v8::Value> QJSValuePrivate::asV8Value(QV8Engine* engine)
 +{
 +    if (!m_engine) {
 +        if (!assignEngine(engine))
 +            return v8::Handle<v8::Value>();
 +    }
 +    Q_ASSERT(isJSBased());
 +    return m_value;
 +}
 +
 +/*!
 +  \internal
 +  Returns true if QSV have an engine associated.
 +*/
 +bool QJSValuePrivate::isJSBased() const
 +{
 +#ifndef QT_NO_DEBUG
 +    // internals check.
 +    if (m_state >= JSValue)
 +        Q_ASSERT(!m_value.IsEmpty());
 +    else
 +        Q_ASSERT(m_value.IsEmpty());
 +#endif
 +    return m_state >= JSValue;
 +}
 +
 +/*!
 +  \internal
 +  Returns true if current value of QSV is placed in m_number.
 +*/
 +bool QJSValuePrivate::isNumberBased() const { return m_state == CNumber || m_state == CBool; }
 +
 +/*!
 +  \internal
 +  Returns true if current value of QSV is placed in m_string.
 +*/
 +bool QJSValuePrivate::isStringBased() const { return m_state == CString; }
 +
 +/*!
 +  \internal
 +  Converts arguments and bind them to the engine.
 +  \attention argv should be big enough
 +*/
 +inline bool QJSValuePrivate::prepareArgumentsForCall(v8::Handle<v8::Value> argv[], const QJSValueList& args) const
 +{
 +    QJSValueList::const_iterator i = args.constBegin();
 +    for (int j = 0; i != args.constEnd(); j++, i++) {
 +        QJSValuePrivate* value = QJSValuePrivate::get(*i);
 +        if ((value->isJSBased() && engine() != value->engine())
 +                || (!value->isJSBased() && !value->assignEngine(engine())))
 +            // Different engines are not allowed!
 +            return false;
 +        argv[j] = *value;
 +    }
 +    return true;
 +}
 +
 +QT_END_NAMESPACE
 +
 +#endif
index 3eccba6,0000000..acfe958
mode 100644,000000..100644
--- /dev/null
@@@ -1,195 -1,0 +1,213 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $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.
 +//
 +
 +#ifndef QJSVALUE_P_H
 +#define QJSVALUE_P_H
 +
 +#include <private/qv8_p.h>
 +
 +#include <QtCore/qbytearray.h>
 +#include <QtCore/qdatetime.h>
 +#include <QtCore/qmath.h>
 +#include <QtCore/qvarlengtharray.h>
 +#include <qdebug.h>
 +
 +#include <private/qintrusivelist_p.h>
 +#include "qscriptshareddata_p.h"
 +#include "qjsvalue.h"
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QV8Engine;
 +
 +/*!
 +  \internal
 +  \class QJSValuePrivate
 +*/
 +class QJSValuePrivate
 +        : public QSharedData
 +{
 +public:
 +    enum PropertyFlag {
 +        ReadOnly            = 0x00000001,
 +        Undeletable         = 0x00000002,
 +        SkipInEnumeration   = 0x00000004
 +    };
 +    Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag)
 +
 +    inline static QJSValuePrivate* get(const QJSValue& q);
 +    inline static QJSValue get(const QJSValuePrivate* d);
 +    inline static QJSValue get(QJSValuePrivate* d);
 +    inline static QJSValue get(QScriptPassPointer<QJSValuePrivate> d);
 +    inline ~QJSValuePrivate();
 +
 +    inline QJSValuePrivate(bool value);
 +    inline QJSValuePrivate(int value);
 +    inline QJSValuePrivate(uint value);
 +    inline QJSValuePrivate(double value);
 +    inline QJSValuePrivate(const QString& value);
 +    inline QJSValuePrivate(QJSValue::SpecialValue value = QJSValue::UndefinedValue);
 +
 +    inline QJSValuePrivate(QV8Engine *engine, bool value);
 +    inline QJSValuePrivate(QV8Engine *engine, int value);
 +    inline QJSValuePrivate(QV8Engine *engine, uint value);
 +    inline QJSValuePrivate(QV8Engine *engine, double value);
 +    inline QJSValuePrivate(QV8Engine *engine, const QString& value);
 +    inline QJSValuePrivate(QV8Engine *engine, QJSValue::SpecialValue value = QJSValue::UndefinedValue);
 +    inline QJSValuePrivate(QV8Engine *engine, v8::Handle<v8::Value>);
 +    inline void invalidate();
 +
 +    inline bool toBool() const;
 +    inline double toNumber() const;
 +    inline QString toString() const;
 +    inline double toInteger() const;
 +    inline qint32 toInt32() const;
 +    inline quint32 toUInt32() const;
 +    inline quint16 toUInt16() const;
 +    inline QDateTime toDataTime() const;
 +    inline QObject *toQObject() const;
 +    inline QVariant toVariant() const;
 +
 +    inline bool isArray() const;
 +    inline bool isBool() const;
 +    inline bool isCallable() const;
 +    inline bool isError() const;
 +    inline bool isFunction() const;
 +    inline bool isNull() const;
 +    inline bool isNumber() const;
 +    inline bool isObject() const;
 +    inline bool isString() const;
 +    inline bool isUndefined() const;
 +    inline bool isVariant() const;
 +    inline bool isDate() const;
 +    inline bool isRegExp() const;
 +    inline bool isQObject() const;
 +
 +    inline bool equals(QJSValuePrivate* other);
 +    inline bool strictlyEquals(QJSValuePrivate* other);
 +    inline bool lessThan(QJSValuePrivate *other) const;
 +
 +    inline QScriptPassPointer<QJSValuePrivate> prototype() const;
 +    inline void setPrototype(QJSValuePrivate* prototype);
 +
 +    inline void setProperty(const QString &name, QJSValuePrivate *value, uint attribs = 0);
 +    inline void setProperty(v8::Handle<v8::String> name, QJSValuePrivate *value, uint attribs = 0);
 +    inline void setProperty(quint32 index, QJSValuePrivate* value, uint attribs = 0);
 +    inline QScriptPassPointer<QJSValuePrivate> property(const QString& name) const;
 +    inline QScriptPassPointer<QJSValuePrivate> property(v8::Handle<v8::String> name) const;
 +    inline QScriptPassPointer<QJSValuePrivate> property(quint32 index) const;
 +    template<typename T>
 +    inline QScriptPassPointer<QJSValuePrivate> property(T name) const;
 +    inline bool deleteProperty(const QString& name);
 +    inline bool hasProperty(const QString &name) const;
 +    inline bool hasOwnProperty(const QString &name) const;
 +    inline PropertyFlags propertyFlags(const QString& name) const;
 +    inline PropertyFlags propertyFlags(v8::Handle<v8::String> name) const;
 +
 +    inline QScriptPassPointer<QJSValuePrivate> call(QJSValuePrivate* thisObject, const QJSValueList& args);
 +    inline QScriptPassPointer<QJSValuePrivate> call(QJSValuePrivate* thisObject, const QJSValue& arguments);
 +    inline QScriptPassPointer<QJSValuePrivate> call(QJSValuePrivate* thisObject, int argc, v8::Handle< v8::Value >* argv);
 +    inline QScriptPassPointer<QJSValuePrivate> callAsConstructor(int argc, v8::Handle<v8::Value> *argv);
 +    inline QScriptPassPointer<QJSValuePrivate> callAsConstructor(const QJSValueList& args);
 +    inline QScriptPassPointer<QJSValuePrivate> callAsConstructor(const QJSValue& arguments);
 +
 +    inline bool assignEngine(QV8Engine *engine);
 +    inline QV8Engine *engine() const;
 +
 +    inline operator v8::Handle<v8::Value>() const;
 +    inline operator v8::Handle<v8::Object>() const;
 +    inline v8::Handle<v8::Value> asV8Value(QV8Engine *engine);
 +private:
 +    QIntrusiveListNode m_node;
 +    QV8Engine *m_engine;
 +
 +    // Please, update class documentation when you change the enum.
 +    enum State {
 +        CString = 0x1000,
 +        CNumber,
 +        CBool,
 +        CNull,
 +        CUndefined,
 +        JSValue = 0x2000, // V8 values are equal or higher then this value.
 +        // JSPrimitive,
 +        // JSObject
 +    } m_state;
 +
 +    union CValue {
 +        bool m_bool;
 +        double m_number;
 +        QString* m_string;
 +
 +        CValue() : m_number(0) {}
 +        CValue(bool value) : m_bool(value) {}
 +        CValue(int number) : m_number(number) {}
 +        CValue(uint number) : m_number(number) {}
 +        CValue(double number) : m_number(number) {}
 +        CValue(QString* string) : m_string(string) {}
 +    } u;
 +    // v8::Persistent is not a POD, so can't be part of the union.
 +    v8::Persistent<v8::Value> m_value;
 +
 +    Q_DISABLE_COPY(QJSValuePrivate)
 +    inline bool isJSBased() const;
 +    inline bool isNumberBased() const;
 +    inline bool isStringBased() const;
 +    inline bool prepareArgumentsForCall(v8::Handle<v8::Value> argv[], const QJSValueList& arguments) const;
 +
 +    friend class QV8Engine;
 +};
 +
 +Q_DECLARE_OPERATORS_FOR_FLAGS(QJSValuePrivate::PropertyFlags)
 +
 +QT_END_NAMESPACE
 +
 +#endif
index c47f07d,0000000..3c1b450
mode 100644,000000..100644
--- /dev/null
@@@ -1,63 -1,0 +1,82 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
- ** If you have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QSCRIPTVALUEITERATOR_H
 +#define QSCRIPTVALUEITERATOR_H
 +
++#include <QtQml/qtqmlglobal.h>
 +#include <QtQml/qjsvalue.h>
 +#include <QtCore/qscopedpointer.h>
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +class QString;
 +
 +class QJSValueIteratorPrivate;
 +class Q_QML_EXPORT QJSValueIterator
 +{
 +public:
 +    QJSValueIterator(const QJSValue &value);
 +    ~QJSValueIterator();
 +
 +    bool hasNext() const;
 +    bool next();
 +
 +    QString name() const;
 +
 +    QJSValue value() const;
 +    QJSValueIterator& operator=(QJSValue &value);
 +
 +private:
 +    QScopedPointer<QJSValueIteratorPrivate> d_ptr;
 +
 +    Q_DECLARE_PRIVATE(QJSValueIterator)
 +    Q_DISABLE_COPY(QJSValueIterator)
 +};
 +
 +QT_END_NAMESPACE
 +
 +QT_END_HEADER
 +
 +#endif // QSCRIPTVALUEITERATOR_H
index 131296e,0000000..2c060b2
mode 100644,000000..100644
--- /dev/null
@@@ -1,121 -1,0 +1,139 @@@
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QJSVALUEITERATOR_IMPL_P_H
 +#define QJSVALUEITERATOR_IMPL_P_H
 +
 +#include "qjsvalueiterator_p.h"
 +#include <private/qv8engine_p.h>
 +#include "qjsconverter_p.h"
 +
 +inline QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValuePrivate* value)
 +    : m_object(const_cast<QJSValuePrivate*>(value))
 +    , m_index(0)
 +    , m_count(0)
 +{
 +    Q_ASSERT(value);
 +    QV8Engine *engine = m_object->engine();
 +    if (!m_object->isObject())
 +        m_object = 0;
 +    else {
 +        QScriptIsolate api(engine, QScriptIsolate::NotNullEngine);
 +        v8::HandleScope scope;
 +
 +        v8::Handle<v8::Value> tmp = *value;
 +        v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(tmp);
 +        v8::Local<v8::Array> names;
 +
 +        // FIXME we need newer V8!
 +        //names = obj->GetOwnPropertyNames();
 +        names = engine->getOwnPropertyNames(obj);
 +        m_names = v8::Persistent<v8::Array>::New(names);
 +        m_count = names->Length();
 +
 +        engine->registerValueIterator(this);
 +    }
 +}
 +
 +inline QJSValueIteratorPrivate::~QJSValueIteratorPrivate()
 +{
 +    if (isValid()) {
 +        engine()->unregisterValueIterator(this);
 +        m_names.Dispose();
 +    }
 +}
 +
 +inline void QJSValueIteratorPrivate::invalidate()
 +{
 +    m_names.Dispose();
 +    m_object.reset();
 +    m_index = 0;
 +    m_count = 0;
 +}
 +
 +inline bool QJSValueIteratorPrivate::hasNext() const
 +{
 +    return isValid() ? m_index < m_count : false;
 +}
 +
 +inline bool QJSValueIteratorPrivate::next()
 +{
 +    if (hasNext()) {
 +        ++m_index;
 +        return true;
 +    }
 +    return false;
 +}
 +
 +inline QString QJSValueIteratorPrivate::name() const
 +{
 +    if (!isValid())
 +        return QString();
 +
 +    v8::HandleScope handleScope;
 +    return QJSConverter::toString(m_names->Get(m_index - 1)->ToString());
 +}
 +
 +inline QScriptPassPointer<QJSValuePrivate> QJSValueIteratorPrivate::value() const
 +{
 +    if (!isValid())
 +        return new QJSValuePrivate();
 +
 +    v8::HandleScope handleScope;
 +    return m_object->property(m_names->Get(m_index - 1)->ToString());
 +}
 +
 +inline bool QJSValueIteratorPrivate::isValid() const
 +{
 +    bool result = m_object ? !m_object->isUndefined() : false;
 +    // We know that if this object is still valid then it is an object
 +    // if this assumption is not correct then some other logic in this class
 +    // have to be changed too.
 +    Q_ASSERT(!result || m_object->isObject());
 +    return result;
 +}
 +
 +inline QV8Engine* QJSValueIteratorPrivate::engine() const
 +{
 +    return m_object ? m_object->engine() : 0;
 +}
 +
 +#endif // QJSVALUEITERATOR_IMPL_P_H
index 2a5bcde,0000000..f5f4c44
mode 100644,000000..100644
--- /dev/null
@@@ -1,68 -1,0 +1,86 @@@
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
- ** If you have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QJSVALUEITERATOR_P_H
 +#define QJSVALUEITERATOR_P_H
 +
 +#include <private/qintrusivelist_p.h>
 +#include "qjsvalue_p.h"
 +
 +#include <private/qv8_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QV8Engine;
 +
 +class QJSValueIteratorPrivate
 +{
 +public:
 +    inline QJSValueIteratorPrivate(const QJSValuePrivate* value);
 +    inline ~QJSValueIteratorPrivate();
 +
 +    inline bool hasNext() const;
 +    inline bool next();
 +
 +    inline QString name() const;
 +
 +    inline QScriptPassPointer<QJSValuePrivate> value() const;
 +
 +    inline bool isValid() const;
 +    inline QV8Engine* engine() const;
 +
 +    inline void invalidate();
 +private:
 +    Q_DISABLE_COPY(QJSValueIteratorPrivate)
 +
 +    QIntrusiveListNode m_node;
 +    QScriptSharedDataPointer<QJSValuePrivate> m_object;
 +    v8::Persistent<v8::Array> m_names;
 +    uint32_t m_index;
 +    uint32_t m_count;
 +
 +    friend class QV8Engine;
 +};
 +
 +
 +QT_END_NAMESPACE
 +
 +#endif // QJSVALUEITERATOR_P_H
index 5284832,0000000..7d7aaa2
mode 100644,000000..100644
--- /dev/null
@@@ -1,1320 -1,0 +1,1321 @@@
-     if (obj)
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qqmlbuiltinfunctions_p.h"
 +
 +#include <QtQml/qqmlcomponent.h>
 +#include <private/qqmlengine_p.h>
 +#include <private/qqmlcomponent_p.h>
 +#include <private/qqmlstringconverters_p.h>
 +#include <private/qqmllocale_p.h>
 +#include <private/qv8engine_p.h>
 +#include <private/qjsconverter_impl_p.h>
 +
 +#include <private/qv8profilerservice_p.h>
 +#include <private/qqmlprofilerservice_p.h>
 +
 +#include <QtCore/qstring.h>
 +#include <QtCore/qdatetime.h>
 +#include <QtCore/qcryptographichash.h>
 +#include <QtCore/qrect.h>
 +#include <QtCore/qsize.h>
 +#include <QtCore/qpoint.h>
 +#include <QtCore/qurl.h>
 +#include <QtCore/qfile.h>
 +#include <QtCore/qcoreapplication.h>
 +
 +#include <QtGui/qcolor.h>
 +#include <QtGui/qvector3d.h>
 +#include <QtGui/qvector4d.h>
 +#include <QtGui/qdesktopservices.h>
 +#include <QtGui/qfontdatabase.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +namespace QQmlBuiltinFunctions {
 +
 +enum ConsoleLogTypes {
 +    Log,
 +    Warn,
 +    Error
 +};
 +
 +static void jsContext(v8::Handle<v8::Value> *file, int *line, v8::Handle<v8::Value> *function) {
 +    v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(1);
 +    if (stackTrace->GetFrameCount()) {
 +        v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(0);
 +        *file = frame->GetScriptName();
 +        *line = frame->GetLineNumber();
 +        *function = frame->GetFunctionName();
 +    }
 +}
 +
 +static QString jsStack() {
 +    QStringList stackFrames;
 +
 +    //The v8 default is currently 10 stack frames.
 +    v8::Handle<v8::StackTrace> stackTrace =
 +        v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
 +    int stackCount = stackTrace->GetFrameCount();
 +
 +    for (int i = 0; i < stackCount; i++) {
 +        v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(i);
 +        v8::Handle<v8::String> function(frame->GetFunctionName());
 +        v8::Handle<v8::String> script(frame->GetScriptName());
 +        int lineNumber = frame->GetLineNumber();
 +        int columnNumber = frame->GetColumn();
 +
 +        QString stackFrame =
 +                QString::fromLatin1("%1 (%2:%3:%4)").arg(QJSConverter::toString(function),
 +                                                         QJSConverter::toString(script),
 +                                                         QString::number(lineNumber),
 +                                                         QString::number(columnNumber));
 +        stackFrames.append(stackFrame);
 +    }
 +    return stackFrames.join(QLatin1String("\n"));
 +}
 +
 +v8::Handle<v8::Value> console(ConsoleLogTypes logType, const v8::Arguments &args,
 +                              bool printStack = false)
 +{
 +    v8::HandleScope handleScope;
 +
 +    QString result;
 +    for (int i = 0; i < args.Length(); ++i) {
 +        if (i != 0)
 +            result.append(QLatin1Char(' '));
 +
 +        v8::Local<v8::Value> value = args[i];
 +        //Check for Object Type
 +        if (value->IsObject() && !value->IsFunction()
 +                && !value->IsArray() && !value->IsDate()
 +                && !value->IsRegExp()) {
 +            result.append(QLatin1String("Object"));
 +        } else {
 +            v8::Local<v8::String> jsstr = value->ToString();
 +            QString tmp = V8ENGINE()->toString(jsstr);
 +            if (value->IsArray())
 +                result.append(QString::fromLatin1("[%1]").arg(tmp));
 +            else
 +                result.append(tmp);
 +        }
 +    }
 +
 +    if (printStack) {
 +        result.append(QLatin1String("\n"));
 +        result.append(jsStack());
 +    }
 +
 +    v8::Handle<v8::Value> fileHandle;
 +    v8::Handle<v8::Value> functionHandle;
 +    int line;
 +
 +    jsContext(&fileHandle, &line, &functionHandle);
 +
 +    switch (logType) {
 +    case Log:
 +        QMessageLogger(*v8::String::AsciiValue(fileHandle), line,
 +                       *v8::String::AsciiValue(functionHandle)).debug("%s", qPrintable(result));
 +        break;
 +    case Warn:
 +        QMessageLogger(*v8::String::AsciiValue(fileHandle), line,
 +                       *v8::String::AsciiValue(functionHandle)).warning("%s", qPrintable(result));
 +        break;
 +    case Error:
 +        QMessageLogger(*v8::String::AsciiValue(fileHandle), line,
 +                       *v8::String::AsciiValue(functionHandle)).critical("%s", qPrintable(result));
 +        break;
 +    default:
 +        break;
 +    }
 +
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> gc(const v8::Arguments &args)
 +{
 +    Q_UNUSED(args);
 +    QV8Engine::gc();
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> consoleError(const v8::Arguments &args)
 +{
 +    return console(Error, args);
 +}
 +
 +v8::Handle<v8::Value> consoleLog(const v8::Arguments &args)
 +{
 +    //console.log
 +    //console.debug
 +    //console.info
 +    //print
 +    return console(Log, args);
 +}
 +
 +v8::Handle<v8::Value> consoleProfile(const v8::Arguments &args)
 +{
 +    //DeclarativeDebugTrace cannot handle nested profiling
 +    //although v8 can handle several profiling at once,
 +    //we do not allow that. Hence, we pass an empty(default) title
 +    Q_UNUSED(args);
 +    QString title;
 +
 +
 +
 +    v8::Handle<v8::Value> file;
 +    v8::Handle<v8::Value> function;
 +    int line;
 +    jsContext(&file, &line, &function);
 +
 +    if (QQmlProfilerService::startProfiling()) {
 +        QV8ProfilerService::instance()->startProfiling(title);
 +
 +        QMessageLogger(*v8::String::AsciiValue(file), line,
 +                       *v8::String::AsciiValue(function)).debug("Profiling started.");
 +    } else {
 +        QMessageLogger(*v8::String::AsciiValue(file), line,
 +                       *v8::String::AsciiValue(function)).warning(
 +                    "Profiling is already in progress. First, end current profiling session.");
 +    }
 +
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> consoleProfileEnd(const v8::Arguments &args)
 +{
 +    //DeclarativeDebugTrace cannot handle nested profiling
 +    //although v8 can handle several profiling at once,
 +    //we do not allow that. Hence, we pass an empty(default) title
 +    Q_UNUSED(args);
 +    QString title;
 +
 +    v8::Handle<v8::Value> file;
 +    v8::Handle<v8::Value> function;
 +    int line;
 +    jsContext(&file, &line, &function);
 +
 +    if (QQmlProfilerService::stopProfiling()) {
 +        QV8ProfilerService *profiler = QV8ProfilerService::instance();
 +        profiler->stopProfiling(title);
 +        QQmlProfilerService::sendProfilingData();
 +        profiler->sendProfilingData();
 +
 +        QMessageLogger(*v8::String::AsciiValue(file), line,
 +                       *v8::String::AsciiValue(function)).debug("Profiling ended.");
 +    } else {
 +        QMessageLogger(*v8::String::AsciiValue(file), line,
 +                       *v8::String::AsciiValue(function)).warning("Profiling was not started.");
 +    }
 +
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> consoleTime(const v8::Arguments &args)
 +{
 +    if (args.Length() != 1)
 +        V8THROW_ERROR("console.time(): Invalid arguments");
 +    QString name = V8ENGINE()->toString(args[0]);
 +    V8ENGINE()->startTimer(name);
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> consoleTimeEnd(const v8::Arguments &args)
 +{
 +    if (args.Length() != 1)
 +        V8THROW_ERROR("console.time(): Invalid arguments");
 +    QString name = V8ENGINE()->toString(args[0]);
 +    bool wasRunning;
 +    qint64 elapsed = V8ENGINE()->stopTimer(name, &wasRunning);
 +    if (wasRunning) {
 +        qDebug("%s: %llims", qPrintable(name), elapsed);
 +    }
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> consoleCount(const v8::Arguments &args)
 +{
 +    // first argument: name to print. Ignore any additional arguments
 +    QString name;
 +    if (args.Length() > 0)
 +        name = V8ENGINE()->toString(args[0]);
 +
 +    v8::Handle<v8::StackTrace> stackTrace =
 +        v8::StackTrace::CurrentStackTrace(1, v8::StackTrace::kOverview);
 +
 +    if (stackTrace->GetFrameCount()) {
 +        v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(0);
 +
 +        QString scriptName = V8ENGINE()->toString(frame->GetScriptName());
 +        QString functionName = V8ENGINE()->toString(frame->GetFunctionName());
 +        int line = frame->GetLineNumber();
 +        int column = frame->GetColumn();
 +
 +        int value = V8ENGINE()->consoleCountHelper(scriptName, line, column);
 +        QString message = name + QLatin1String(": ") + QString::number(value);
 +
 +        QMessageLogger(qPrintable(scriptName), line,
 +                       qPrintable(functionName)).debug("%s", qPrintable(message));
 +    }
 +
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> consoleTrace(const v8::Arguments &args)
 +{
 +    if (args.Length() != 0)
 +        V8THROW_ERROR("console.trace(): Invalid arguments");
 +
 +    QString stack = jsStack();
 +
 +    v8::Handle<v8::Value> file;
 +    v8::Handle<v8::Value> function;
 +    int line;
 +    jsContext(&file, &line, &function);
 +
 +    QMessageLogger(*v8::String::AsciiValue(file), line, *v8::String::AsciiValue(function)).debug(
 +                "%s", qPrintable(stack));
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> consoleWarn(const v8::Arguments &args)
 +{
 +    return console(Warn, args);
 +}
 +
 +v8::Handle<v8::Value> consoleAssert(const v8::Arguments &args)
 +{
 +    if (args.Length() == 0)
 +        V8THROW_ERROR("console.assert(): Missing argument");
 +
 +    if (!args[0]->ToBoolean()->Value()) {
 +        QString message;
 +        for (int i = 1; i < args.Length(); ++i) {
 +            if (i != 1)
 +                message.append(QLatin1Char(' '));
 +
 +            v8::Local<v8::Value> value = args[i];
 +            message.append(V8ENGINE()->toString(value->ToString()));
 +        }
 +
 +        QString stack = jsStack();
 +
 +        v8::Handle<v8::Value> file;
 +        v8::Handle<v8::Value> function;
 +        int line;
 +        jsContext(&file, &line, &function);
 +
 +        QMessageLogger(*v8::String::AsciiValue(file), line, *v8::String::AsciiValue(function)).critical(
 +                    "%s\n%s", qPrintable(message), qPrintable(stack));
 +
 +    }
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> consoleException(const v8::Arguments &args)
 +{
 +    if (args.Length() == 0)
 +        V8THROW_ERROR("console.exception(): Missing argument");
 +
 +    console(Error, args, true);
 +
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> stringArg(const v8::Arguments &args)
 +{
 +    QString value = V8ENGINE()->toString(args.This()->ToString());
 +    if (args.Length() != 1)
 +        V8THROW_ERROR("String.arg(): Invalid arguments");
 +
 +    v8::Handle<v8::Value> arg = args[0];
 +    if (arg->IsUint32())
 +        return V8ENGINE()->toString(value.arg(arg->Uint32Value()));
 +    else if (arg->IsInt32())
 +        return V8ENGINE()->toString(value.arg(arg->Int32Value()));
 +    else if (arg->IsNumber())
 +        return V8ENGINE()->toString(value.arg(arg->NumberValue()));
 +    else if (arg->IsBoolean())
 +        return V8ENGINE()->toString(value.arg(arg->BooleanValue()));
 +
 +    return V8ENGINE()->toString(value.arg(V8ENGINE()->toString(arg)));
 +}
 +
 +/*!
 +\qmlmethod bool Qt::isQtObject(object)
 +Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
 +*/
 +v8::Handle<v8::Value> isQtObject(const v8::Arguments &args)
 +{
 +    if (args.Length() == 0)
 +        return v8::Boolean::New(false);
 +
 +    return v8::Boolean::New(0 != V8ENGINE()->toQObject(args[0]));
 +}
 +
 +/*!
 +\qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
 +
 +Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
 +All components should be in the range 0-1 inclusive.
 +*/
 +v8::Handle<v8::Value> rgba(const v8::Arguments &args)
 +{
 +    int argCount = args.Length();
 +    if (argCount < 3 || argCount > 4)
 +        V8THROW_ERROR("Qt.rgba(): Invalid arguments");
 +
 +    double r = args[0]->NumberValue();
 +    double g = args[1]->NumberValue();
 +    double b = args[2]->NumberValue();
 +    double a = (argCount == 4) ? args[3]->NumberValue() : 1;
 +
 +    if (r < 0.0) r=0.0;
 +    if (r > 1.0) r=1.0;
 +    if (g < 0.0) g=0.0;
 +    if (g > 1.0) g=1.0;
 +    if (b < 0.0) b=0.0;
 +    if (b > 1.0) b=1.0;
 +    if (a < 0.0) a=0.0;
 +    if (a > 1.0) a=1.0;
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromRgbF(r, g, b, a)));
 +}
 +
 +/*!
 +\qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
 +
 +Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
 +All components should be in the range 0-1 inclusive.
 +*/
 +v8::Handle<v8::Value> hsla(const v8::Arguments &args)
 +{
 +    int argCount = args.Length();
 +    if (argCount < 3 || argCount > 4)
 +        V8THROW_ERROR("Qt.hsla(): Invalid arguments");
 +
 +    double h = args[0]->NumberValue();
 +    double s = args[1]->NumberValue();
 +    double l = args[2]->NumberValue();
 +    double a = (argCount == 4) ? args[3]->NumberValue() : 1;
 +
 +    if (h < 0.0) h=0.0;
 +    if (h > 1.0) h=1.0;
 +    if (s < 0.0) s=0.0;
 +    if (s > 1.0) s=1.0;
 +    if (l < 0.0) l=0.0;
 +    if (l > 1.0) l=1.0;
 +    if (a < 0.0) a=0.0;
 +    if (a > 1.0) a=1.0;
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromHslF(h, s, l, a)));
 +}
 +
 +/*!
 +\qmlmethod rect Qt::rect(int x, int y, int width, int height)
 +
 +Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
 +
 +The returned object has \c x, \c y, \c width and \c height attributes with the given values.
 +*/
 +v8::Handle<v8::Value> rect(const v8::Arguments &args)
 +{
 +    if (args.Length() != 4)
 +        V8THROW_ERROR("Qt.rect(): Invalid arguments");
 +
 +    double x = args[0]->NumberValue();
 +    double y = args[1]->NumberValue();
 +    double w = args[2]->NumberValue();
 +    double h = args[3]->NumberValue();
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
 +}
 +
 +/*!
 +\qmlmethod point Qt::point(int x, int y)
 +Returns a Point with the specified \c x and \c y coordinates.
 +*/
 +v8::Handle<v8::Value> point(const v8::Arguments &args)
 +{
 +    if (args.Length() != 2)
 +        V8THROW_ERROR("Qt.point(): Invalid arguments");
 +
 +    double x = args[0]->ToNumber()->Value();
 +    double y = args[1]->ToNumber()->Value();
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(QPointF(x, y)));
 +}
 +
 +/*!
 +\qmlmethod Qt::size(int width, int height)
 +Returns a Size with the specified \c width and \c height.
 +*/
 +v8::Handle<v8::Value> size(const v8::Arguments &args)
 +{
 +    if (args.Length() != 2)
 +        V8THROW_ERROR("Qt.size(): Invalid arguments");
 +
 +    double w = args[0]->ToNumber()->Value();
 +    double h = args[1]->ToNumber()->Value();
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(QSizeF(w, h)));
 +}
 +
 +/*!
 +\qmlmethod Qt::vector3d(real x, real y, real z)
 +Returns a Vector3D with the specified \c x, \c y and \c z.
 +*/
 +v8::Handle<v8::Value> vector3d(const v8::Arguments &args)
 +{
 +    if (args.Length() != 3)
 +        V8THROW_ERROR("Qt.vector(): Invalid arguments");
 +
 +    double x = args[0]->ToNumber()->Value();
 +    double y = args[1]->ToNumber()->Value();
 +    double z = args[2]->ToNumber()->Value();
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(QVector3D(x, y, z)));
 +}
 +
 +/*!
 +\qmlmethod Qt::vector4d(real x, real y, real z, real w)
 +Returns a Vector4D with the specified \c x, \c y, \c z and \c w.
 +*/
 +v8::Handle<v8::Value> vector4d(const v8::Arguments &args)
 +{
 +    if (args.Length() != 4)
 +        V8THROW_ERROR("Qt.vector4d(): Invalid arguments");
 +
 +    double x = args[0]->NumberValue();
 +    double y = args[1]->NumberValue();
 +    double z = args[2]->NumberValue();
 +    double w = args[3]->NumberValue();
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(QVector4D(x, y, z, w)));
 +}
 +
 +/*!
 +\qmlmethod color Qt::lighter(color baseColor, real factor)
 +Returns a color lighter than \c baseColor by the \c factor provided.
 +
 +If the factor is greater than 1.0, this functions returns a lighter color.
 +Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
 +the return color is darker, but we recommend using the Qt.darker() function for this purpose.
 +If the factor is 0 or negative, the return value is unspecified.
 +
 +The function converts the current RGB color to HSV, multiplies the value (V) component
 +by factor and converts the color back to RGB.
 +
 +If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
 +*/
 +v8::Handle<v8::Value> lighter(const v8::Arguments &args)
 +{
 +    if (args.Length() != 1 && args.Length() != 2)
 +        V8THROW_ERROR("Qt.lighter(): Invalid arguments");
 +
 +    QColor color;
 +    QVariant v = V8ENGINE()->toVariant(args[0], -1);
 +    if (v.userType() == QVariant::Color) {
 +        color = v.value<QColor>();
 +    } else if (v.userType() == QVariant::String) {
 +        bool ok = false;
 +        color = QQmlStringConverters::colorFromString(v.toString(), &ok);
 +        if (!ok) {
 +            return v8::Null();
 +        }
 +    } else {
 +        return v8::Null();
 +    }
 +
 +    qreal factor = 1.5;
 +    if (args.Length() == 2)
 +        factor = args[1]->ToNumber()->Value();
 +
 +    color = color.lighter(int(qRound(factor*100.)));
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(color));
 +}
 +
 +/*!
 +\qmlmethod color Qt::darker(color baseColor, real factor)
 +Returns a color darker than \c baseColor by the \c factor provided.
 +
 +If the factor is greater than 1.0, this function returns a darker color.
 +Setting factor to 3.0 returns a color that has one-third the brightness.
 +If the factor is less than 1.0, the return color is lighter, but we recommend using
 +the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
 +value is unspecified.
 +
 +The function converts the current RGB color to HSV, divides the value (V) component
 +by factor and converts the color back to RGB.
 +
 +If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
 +*/
 +v8::Handle<v8::Value> darker(const v8::Arguments &args)
 +{
 +    if (args.Length() != 1 && args.Length() != 2)
 +        V8THROW_ERROR("Qt.darker(): Invalid arguments");
 +
 +    QColor color;
 +    QVariant v = V8ENGINE()->toVariant(args[0], -1);
 +    if (v.userType() == QVariant::Color) {
 +        color = v.value<QColor>();
 +    } else if (v.userType() == QVariant::String) {
 +        bool ok = false;
 +        color = QQmlStringConverters::colorFromString(v.toString(), &ok);
 +        if (!ok) {
 +            return v8::Null();
 +        }
 +    } else {
 +        return v8::Null();
 +    }
 +
 +    qreal factor = 2.0;
 +    if (args.Length() == 2)
 +        factor = args[1]->ToNumber()->Value();
 +
 +    color = color.darker(int(qRound(factor*100.)));
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(color));
 +}
 +
 +/*!
 +    \qmlmethod color Qt::tint(color baseColor, color tintColor)
 +    This function allows tinting one color with another.
 +
 +    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
 +    Item {
 +        Rectangle {
 +            x: 0; width: 80; height: 80
 +            color: "lightsteelblue"
 +        }
 +        Rectangle {
 +            x: 100; width: 80; height: 80
 +            color: Qt.tint("lightsteelblue", "#10FF0000")
 +        }
 +    }
 +    \endqml
 +    \image declarative-rect_tint.png
 +
 +    Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
 +*/
 +v8::Handle<v8::Value> tint(const v8::Arguments &args)
 +{
 +    if (args.Length() != 2)
 +        V8THROW_ERROR("Qt.tint(): Invalid arguments");
 +
 +    // base color
 +    QColor color;
 +    QVariant v = V8ENGINE()->toVariant(args[0], -1);
 +    if (v.userType() == QVariant::Color) {
 +        color = v.value<QColor>();
 +    } else if (v.userType() == QVariant::String) {
 +        bool ok = false;
 +        color = QQmlStringConverters::colorFromString(v.toString(), &ok);
 +        if (!ok) {
 +            return v8::Null();
 +        }
 +    } else {
 +        return v8::Null();
 +    }
 +
 +    // tint color
 +    QColor tintColor;
 +    v = V8ENGINE()->toVariant(args[1], -1);
 +    if (v.userType() == QVariant::Color) {
 +        tintColor = v.value<QColor>();
 +    } else if (v.userType() == QVariant::String) {
 +        bool ok = false;
 +        tintColor = QQmlStringConverters::colorFromString(v.toString(), &ok);
 +        if (!ok) {
 +            return v8::Null();
 +        }
 +    } else {
 +        return v8::Null();
 +    }
 +
 +    // tint the base color and return the final color
 +    QColor finalColor;
 +    int a = tintColor.alpha();
 +    if (a == 0xFF)
 +        finalColor = tintColor;
 +    else if (a == 0x00)
 +        finalColor = color;
 +    else {
 +        qreal a = tintColor.alphaF();
 +        qreal inv_a = 1.0 - a;
 +
 +        finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
 +                           tintColor.greenF() * a + color.greenF() * inv_a,
 +                           tintColor.blueF() * a + color.blueF() * inv_a,
 +                           a + inv_a * color.alphaF());
 +    }
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(finalColor));
 +}
 +
 +/*!
 +\qmlmethod string Qt::formatDate(datetime date, variant format)
 +
 +Returns a string representation of \c date, optionally formatted according
 +to \c format.
 +
 +The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
 +property, a QDate, or QDateTime value. The \a format parameter may be any of
 +the possible format values as described for
 +\l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
 +
 +If \a format is not specified, \a date is formatted using
 +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
 +
 +\sa Locale
 +*/
 +v8::Handle<v8::Value> formatDate(const v8::Arguments &args)
 +{
 +    if (args.Length() < 1 || args.Length() > 2)
 +        V8THROW_ERROR("Qt.formatDate(): Invalid arguments");
 +
 +    Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
 +    QDate date = V8ENGINE()->toVariant(args[0], -1).toDateTime().date();
 +    QString formattedDate;
 +    if (args.Length() == 2) {
 +        if (args[1]->IsString()) {
 +            QString format = V8ENGINE()->toVariant(args[1], -1).toString();
 +            formattedDate = date.toString(format);
 +        } else if (args[1]->IsNumber()) {
 +            quint32 intFormat = args[1]->ToNumber()->Value();
 +            Qt::DateFormat format = Qt::DateFormat(intFormat);
 +            formattedDate = date.toString(format);
 +        } else {
 +            V8THROW_ERROR("Qt.formatDate(): Invalid date format");
 +        }
 +    } else {
 +         formattedDate = date.toString(enumFormat);
 +    }
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDate));
 +}
 +
 +/*!
 +\qmlmethod string Qt::formatTime(datetime time, variant format)
 +
 +Returns a string representation of \c time, optionally formatted according to
 +\c format.
 +
 +The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
 +value. The \a format parameter may be any of the possible format values as
 +described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
 +
 +If \a format is not specified, \a time is formatted using
 +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
 +
 +\sa Locale
 +*/
 +v8::Handle<v8::Value> formatTime(const v8::Arguments &args)
 +{
 +    if (args.Length() < 1 || args.Length() > 2)
 +        V8THROW_ERROR("Qt.formatTime(): Invalid arguments");
 +
 +    QVariant argVariant = V8ENGINE()->toVariant(args[0], -1);
 +    QTime time;
 +    if (args[0]->IsDate() || (argVariant.type() == QVariant::String))
 +        time = argVariant.toDateTime().time();
 +    else // if (argVariant.type() == QVariant::Time), or invalid.
 +        time = argVariant.toTime();
 +
 +    Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
 +    QString formattedTime;
 +    if (args.Length() == 2) {
 +        if (args[1]->IsString()) {
 +            QString format = V8ENGINE()->toVariant(args[1], -1).toString();
 +            formattedTime = time.toString(format);
 +        } else if (args[1]->IsNumber()) {
 +            quint32 intFormat = args[1]->ToNumber()->Value();
 +            Qt::DateFormat format = Qt::DateFormat(intFormat);
 +            formattedTime = time.toString(format);
 +        } else {
 +            V8THROW_ERROR("Qt.formatTime(): Invalid time format");
 +        }
 +    } else {
 +         formattedTime = time.toString(enumFormat);
 +    }
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(formattedTime));
 +}
 +
 +/*!
 +\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
 +
 +Returns a string representation of \c datetime, optionally formatted according to
 +\c format.
 +
 +The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
 +property, a QDate, QTime, or QDateTime value.
 +
 +If \a format is not provided, \a dateTime is formatted using
 +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise,
 +\a format should be either:
 +
 +\list
 +\o One of the Qt::DateFormat enumeration values, such as
 +   \c Qt.DefaultLocaleShortDate or \c Qt.ISODate
 +\o A string that specifies the format of the returned string, as detailed below.
 +\endlist
 +
 +If \a format specifies a format string, it should use the following expressions
 +to specify the date:
 +
 +    \table
 +    \header \i Expression \i Output
 +    \row \i d \i the day as number without a leading zero (1 to 31)
 +    \row \i dd \i the day as number with a leading zero (01 to 31)
 +    \row \i ddd
 +            \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
 +            Uses QDate::shortDayName().
 +    \row \i dddd
 +            \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
 +            Uses QDate::longDayName().
 +    \row \i M \i the month as number without a leading zero (1-12)
 +    \row \i MM \i the month as number with a leading zero (01-12)
 +    \row \i MMM
 +            \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
 +            Uses QDate::shortMonthName().
 +    \row \i MMMM
 +            \i the long localized month name (e.g. 'January' to 'December').
 +            Uses QDate::longMonthName().
 +    \row \i yy \i the year as two digit number (00-99)
 +    \row \i yyyy \i the year as four digit number
 +    \endtable
 +
 +In addition the following expressions can be used to specify the time:
 +
 +    \table
 +    \header \i Expression \i Output
 +    \row \i h
 +         \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
 +    \row \i hh
 +         \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
 +    \row \i m \i the minute without a leading zero (0 to 59)
 +    \row \i mm \i the minute with a leading zero (00 to 59)
 +    \row \i s \i the second without a leading zero (0 to 59)
 +    \row \i ss \i the second with a leading zero (00 to 59)
 +    \row \i z \i the milliseconds without leading zeroes (0 to 999)
 +    \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
 +    \row \i AP
 +            \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
 +    \row \i ap
 +            \i use am/pm display. \e ap will be replaced by either "am" or "pm".
 +    \endtable
 +
 +    All other input characters will be ignored. Any sequence of characters that
 +    are enclosed in single quotes will be treated as text and not be used as an
 +    expression. Two consecutive single quotes ("''") are replaced by a single quote
 +    in the output.
 +
 +For example, if the following date/time value was specified:
 +
 +    \code
 +    // 21 May 2001 14:13:09
 +    var dateTime = new Date(2001, 5, 21, 14, 13, 09)
 +    \endcode
 +
 +This \a dateTime value could be passed to \c Qt.formatDateTime(),
 +\l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()}
 +with the \a format values below to produce the following results:
 +
 +    \table
 +    \header \i Format \i Result
 +    \row \i "dd.MM.yyyy"      \i 21.05.2001
 +    \row \i "ddd MMMM d yy"   \i Tue May 21 01
 +    \row \i "hh:mm:ss.zzz"    \i 14:13:09.042
 +    \row \i "h:m:s ap"        \i 2:13:9 pm
 +    \endtable
 +
 +    \sa Locale
 +*/
 +v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args)
 +{
 +    if (args.Length() < 1 || args.Length() > 2)
 +        V8THROW_ERROR("Qt.formatDateTime(): Invalid arguments");
 +
 +    Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
 +    QDateTime dt = V8ENGINE()->toVariant(args[0], -1).toDateTime();
 +    QString formattedDt;
 +    if (args.Length() == 2) {
 +        if (args[1]->IsString()) {
 +            QString format = V8ENGINE()->toVariant(args[1], -1).toString();
 +            formattedDt = dt.toString(format);
 +        } else if (args[1]->IsNumber()) {
 +            quint32 intFormat = args[1]->ToNumber()->Value();
 +            Qt::DateFormat format = Qt::DateFormat(intFormat);
 +            formattedDt = dt.toString(format);
 +        } else {
 +            V8THROW_ERROR("Qt.formatDateTime(): Invalid datetime format");
 +        }
 +    } else {
 +         formattedDt = dt.toString(enumFormat);
 +    }
 +
 +    return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDt));
 +}
 +
 +/*!
 +\qmlmethod bool Qt::openUrlExternally(url target)
 +Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise.
 +*/
 +v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args)
 +{
 +    if (args.Length() != 1)
 +        return V8ENGINE()->fromVariant(false);
 +
 +    bool ret = false;
 +#ifndef QT_NO_DESKTOPSERVICES
 +    ret = QDesktopServices::openUrl(V8ENGINE()->toVariant(resolvedUrl(args), -1).toUrl());
 +#endif
 +    return V8ENGINE()->fromVariant(ret);
 +}
 +
 +/*!
 +  \qmlmethod url Qt::resolvedUrl(url url)
 +  Returns \a url resolved relative to the URL of the caller.
 +*/
 +v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args)
 +{
 +    QUrl url = V8ENGINE()->toVariant(args[0], -1).toUrl();
 +    QQmlEngine *e = V8ENGINE()->engine();
 +    QQmlEnginePrivate *p = 0;
 +    if (e) p = QQmlEnginePrivate::get(e);
 +    if (p) {
 +        QQmlContextData *ctxt = V8ENGINE()->callingContext();
 +        if (ctxt)
 +            return V8ENGINE()->toString(ctxt->resolvedUrl(url).toString());
 +        else
 +            return V8ENGINE()->toString(url.toString());
 +    }
 +
 +    return V8ENGINE()->toString(e->baseUrl().resolved(url).toString());
 +}
 +
 +/*!
 +\qmlmethod list<string> Qt::fontFamilies()
 +Returns a list of the font families available to the application.
 +*/
 +v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args)
 +{
 +    if (args.Length() != 0)
 +        V8THROW_ERROR("Qt.fontFamilies(): Invalid arguments");
 +
 +    QFontDatabase database;
 +    return V8ENGINE()->fromVariant(database.families());
 +}
 +
 +/*!
 +\qmlmethod string Qt::md5(data)
 +Returns a hex string of the md5 hash of \c data.
 +*/
 +v8::Handle<v8::Value> md5(const v8::Arguments &args)
 +{
 +    if (args.Length() != 1)
 +        V8THROW_ERROR("Qt.md5(): Invalid arguments");
 +
 +    QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
 +    QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
 +    return V8ENGINE()->toString(QLatin1String(result.toHex()));
 +}
 +
 +/*!
 +\qmlmethod string Qt::btoa(data)
 +Binary to ASCII - this function returns a base64 encoding of \c data.
 +*/
 +v8::Handle<v8::Value> btoa(const v8::Arguments &args)
 +{
 +    if (args.Length() != 1)
 +        V8THROW_ERROR("Qt.btoa(): Invalid arguments");
 +
 +    QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
 +
 +    return V8ENGINE()->toString(QLatin1String(data.toBase64()));
 +}
 +
 +/*!
 +\qmlmethod string Qt::atob(data)
 +ASCII to binary - this function returns a base64 decoding of \c data.
 +*/
 +v8::Handle<v8::Value> atob(const v8::Arguments &args)
 +{
 +    if (args.Length() != 1)
 +        V8THROW_ERROR("Qt.atob(): Invalid arguments");
 +
 +    QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
 +
 +    return V8ENGINE()->toString(QLatin1String(QByteArray::fromBase64(data)));
 +}
 +
 +/*!
 +\qmlmethod Qt::quit()
 +This function causes the QQmlEngine::quit() signal to be emitted.
 +Within the \l {QML Viewer}, this causes the launcher application to exit;
 +to quit a C++ application when this method is called, connect the
 +QQmlEngine::quit() signal to the QCoreApplication::quit() slot.
 +*/
 +v8::Handle<v8::Value> quit(const v8::Arguments &args)
 +{
 +    QQmlEnginePrivate::get(V8ENGINE()->engine())->sendQuit();
 +    return v8::Undefined();
 +}
 +
 +/*!
 +\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
 +
 +Returns a new object created from the given \a string of QML which will have the specified \a parent,
 +or \c null if there was an error in creating the object.
 +
 +If \a filepath is specified, it will be used for error reporting for the created object.
 +
 +Example (where \c parentItem is the id of an existing QML item):
 +
 +\snippet doc/src/snippets/qml/createQmlObject.qml 0
 +
 +In the case of an error, a QtScript Error object is thrown. This object has an additional property,
 +\c qmlErrors, which is an array of the errors encountered.
 +Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
 +For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
 +{ "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
 +
 +Note that this function returns immediately, and therefore may not work if
 +the \a qml string loads new components (that is, external QML files that have not yet been loaded).
 +If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead.
 +
 +See \l {Dynamic Object Management in QML} for more information on using this function.
 +*/
 +v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args)
 +{
 +    if (args.Length() < 2 || args.Length() > 3)
 +        V8THROW_ERROR("Qt.createQmlObject(): Invalid arguments");
 +
 +    struct Error {
 +        static v8::Local<v8::Value> create(QV8Engine *engine, const QList<QQmlError> &errors) {
 +            QString errorstr = QLatin1String("Qt.createQmlObject(): failed to create object: ");
 +
 +            v8::Local<v8::Array> qmlerrors = v8::Array::New(errors.count());
 +            for (int ii = 0; ii < errors.count(); ++ii) {
 +                const QQmlError &error = errors.at(ii);
 +                errorstr += QLatin1String("\n    ") + error.toString();
 +                v8::Local<v8::Object> qmlerror = v8::Object::New();
 +                qmlerror->Set(v8::String::New("lineNumber"), v8::Integer::New(error.line()));
 +                qmlerror->Set(v8::String::New("columnNumber"), v8::Integer::New(error.column()));
 +                qmlerror->Set(v8::String::New("fileName"), engine->toString(error.url().toString()));
 +                qmlerror->Set(v8::String::New("message"), engine->toString(error.description()));
 +                qmlerrors->Set(ii, qmlerror);
 +            }
 +
 +            v8::Local<v8::Value> error = v8::Exception::Error(engine->toString(errorstr));
 +            v8::Local<v8::Object> errorObject = error->ToObject();
 +            errorObject->Set(v8::String::New("qmlErrors"), qmlerrors);
 +            return error;
 +        }
 +    };
 +
 +    QV8Engine *v8engine = V8ENGINE();
 +    QQmlEngine *engine = v8engine->engine();
 +
 +    QQmlContextData *context = v8engine->callingContext();
 +    QQmlContext *effectiveContext = 0;
 +    if (context->isPragmaLibraryContext)
 +        effectiveContext = engine->rootContext();
 +    else
 +        effectiveContext = context->asQQmlContext();
 +    Q_ASSERT(context && effectiveContext);
 +
 +    QString qml = v8engine->toString(args[0]->ToString());
 +    if (qml.isEmpty())
 +        return v8::Null();
 +
 +    QUrl url;
 +    if (args.Length() > 2)
 +        url = QUrl(v8engine->toString(args[2]->ToString()));
 +    else
 +        url = QUrl(QLatin1String("inline"));
 +
 +    if (url.isValid() && url.isRelative())
 +        url = context->resolvedUrl(url);
 +
 +    QObject *parentArg = v8engine->toQObject(args[1]);
 +    if (!parentArg)
 +        V8THROW_ERROR("Qt.createQmlObject(): Missing parent object");
 +
 +    QQmlComponent component(engine);
 +    component.setData(qml.toUtf8(), url);
 +
 +    if (component.isError()) {
 +        v8::ThrowException(Error::create(v8engine, component.errors()));
 +        return v8::Undefined();
 +    }
 +
 +    if (!component.isReady())
 +        V8THROW_ERROR("Qt.createQmlObject(): Component is not ready");
 +
 +    QObject *obj = component.beginCreate(effectiveContext);
-     obj->setParent(parentArg);
-     QList<QQmlPrivate::AutoParentFunction> functions = QQmlMetaType::parentFunctions();
-     for (int ii = 0; ii < functions.count(); ++ii) {
-         if (QQmlPrivate::Parented == functions.at(ii)(obj, parentArg))
-             break;
-     }
++    if (obj) {
 +        QQmlData::get(obj, true)->setImplicitDestructible();
++
++        obj->setParent(parentArg);
++
++        QList<QQmlPrivate::AutoParentFunction> functions = QQmlMetaType::parentFunctions();
++        for (int ii = 0; ii < functions.count(); ++ii) {
++            if (QQmlPrivate::Parented == functions.at(ii)(obj, parentArg))
++                break;
++        }
++    }
 +    component.completeCreate();
 +
 +    if (component.isError()) {
 +        v8::ThrowException(Error::create(v8engine, component.errors()));
 +        return v8::Undefined();
 +    }
 +
 +    Q_ASSERT(obj);
 +
 +    return v8engine->newQObject(obj);
 +}
 +
 +/*!
 +\qmlmethod object Qt::createComponent(url)
 +
 +Returns a \l Component object created using the QML file at the specified \a url,
 +or \c null if an empty string was given.
 +
 +The returned component's \l Component::status property indicates whether the
 +component was successfully created. If the status is \c Component.Error,
 +see \l Component::errorString() for an error description.
 +
 +Call \l {Component::createObject()}{Component.createObject()} on the returned
 +component to create an object instance of the component.
 +
 +For example:
 +
 +\snippet doc/src/snippets/qml/createComponent-simple.qml 0
 +
 +See \l {Dynamic Object Management in QML} for more information on using this function.
 +
 +To create a QML object from an arbitrary string of QML (instead of a file),
 +use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
 +*/
 +v8::Handle<v8::Value> createComponent(const v8::Arguments &args)
 +{
 +    if (args.Length() != 1)
 +        V8THROW_ERROR("Qt.createComponent(): Invalid arguments");
 +
 +    QV8Engine *v8engine = V8ENGINE();
 +    QQmlEngine *engine = v8engine->engine();
 +
 +    QQmlContextData *context = v8engine->callingContext();
 +    QQmlContextData *effectiveContext = context;
 +    if (context->isPragmaLibraryContext)
 +        effectiveContext = 0;
 +    Q_ASSERT(context);
 +
 +    QString arg = v8engine->toString(args[0]->ToString());
 +    if (arg.isEmpty())
 +        return v8::Null();
 +
 +    QUrl url = context->resolvedUrl(QUrl(arg));
 +    QQmlComponent *c = new QQmlComponent(engine, url, engine);
 +    QQmlComponentPrivate::get(c)->creationContext = effectiveContext;
 +    QQmlData::get(c, true)->setImplicitDestructible();
 +    return v8engine->newQObject(c);
 +}
 +
 +v8::Handle<v8::Value> qsTranslate(const v8::Arguments &args)
 +{
 +    if (args.Length() < 2)
 +        V8THROW_ERROR("qsTranslate() requires at least two arguments");
 +    if (!args[0]->IsString())
 +        V8THROW_ERROR("qsTranslate(): first argument (context) must be a string");
 +    if (!args[1]->IsString())
 +        V8THROW_ERROR("qsTranslate(): second argument (text) must be a string");
 +    if ((args.Length() > 2) && !args[2]->IsString())
 +        V8THROW_ERROR("qsTranslate(): third argument (comment) must be a string");
 +    if ((args.Length() > 3) && !args[3]->IsString())
 +        V8THROW_ERROR("qsTranslate(): fourth argument (encoding) must be a string");
 +
 +    QV8Engine *v8engine = V8ENGINE();
 +    QString context = v8engine->toString(args[0]);
 +    QString text = v8engine->toString(args[1]);
 +    QString comment;
 +    if (args.Length() > 2) comment = v8engine->toString(args[2]);
 +
 +    QCoreApplication::Encoding encoding = QCoreApplication::UnicodeUTF8;
 +    if (args.Length() > 3) {
 +        QString encStr = v8engine->toString(args[3]);
 +        if (encStr == QLatin1String("CodecForTr")) {
 +            encoding = QCoreApplication::CodecForTr;
 +        } else if (encStr == QLatin1String("UnicodeUTF8")) {
 +            encoding = QCoreApplication::UnicodeUTF8;
 +        } else {
 +            QString msg = QString::fromLatin1("qsTranslate(): invalid encoding '%0'").arg(encStr);
 +            V8THROW_ERROR((uint16_t *)msg.constData());
 +        }
 +    }
 +
 +    int n = -1;
 +    if (args.Length() > 4)
 +        n = args[4]->Int32Value();
 +
 +    QString result = QCoreApplication::translate(context.toUtf8().constData(),
 +                                                 text.toUtf8().constData(),
 +                                                 comment.toUtf8().constData(),
 +                                                 encoding, n);
 +
 +    return v8engine->toString(result);
 +}
 +
 +v8::Handle<v8::Value> qsTranslateNoOp(const v8::Arguments &args)
 +{
 +    if (args.Length() < 2)
 +        return v8::Undefined();
 +    return args[1];
 +}
 +
 +v8::Handle<v8::Value> qsTr(const v8::Arguments &args)
 +{
 +    if (args.Length() < 1)
 +        V8THROW_ERROR("qsTr() requires at least one argument");
 +    if (!args[0]->IsString())
 +        V8THROW_ERROR("qsTr(): first argument (text) must be a string");
 +    if ((args.Length() > 1) && !args[1]->IsString())
 +        V8THROW_ERROR("qsTr(): second argument (comment) must be a string");
 +    if ((args.Length() > 2) && !args[2]->IsNumber())
 +        V8THROW_ERROR("qsTr(): third argument (n) must be a number");
 +
 +    QV8Engine *v8engine = V8ENGINE();
 +    QQmlContextData *ctxt = v8engine->callingContext();
 +
 +    QString path = ctxt->url.toString();
 +    int lastSlash = path.lastIndexOf(QLatin1Char('/'));
 +    QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) : QString();
 +
 +    QString text = v8engine->toString(args[0]);
 +    QString comment;
 +    if (args.Length() > 1)
 +        comment = v8engine->toString(args[1]);
 +    int n = -1;
 +    if (args.Length() > 2)
 +        n = args[2]->Int32Value();
 +
 +    QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(),
 +                                                 comment.toUtf8().constData(), QCoreApplication::UnicodeUTF8, n);
 +
 +    return v8engine->toString(result);
 +}
 +
 +v8::Handle<v8::Value> qsTrNoOp(const v8::Arguments &args)
 +{
 +    if (args.Length() < 1)
 +        return v8::Undefined();
 +    return args[0];
 +}
 +
 +v8::Handle<v8::Value> qsTrId(const v8::Arguments &args)
 +{
 +    if (args.Length() < 1)
 +        V8THROW_ERROR("qsTrId() requires at least one argument");
 +    if (!args[0]->IsString())
 +        V8THROW_TYPE("qsTrId(): first argument (id) must be a string");
 +    if (args.Length() > 1 && !args[1]->IsNumber())
 +        V8THROW_TYPE("qsTrId(): second argument (n) must be a number");
 +
 +    int n = -1;
 +    if (args.Length() > 1)
 +        n = args[1]->Int32Value();
 +
 +    QV8Engine *v8engine = V8ENGINE();
 +    return v8engine->toString(qtTrId(v8engine->toString(args[0]).toUtf8().constData(), n));
 +}
 +
 +v8::Handle<v8::Value> qsTrIdNoOp(const v8::Arguments &args)
 +{
 +    if (args.Length() < 1)
 +        return v8::Undefined();
 +    return args[0];
 +}
 +
 +
 +/*!
 +    \qmlmethod Qt::locale(name)
 +
 +    Returns a JS object representing the locale with the specified
 +    name, which has the format "language[_territory][.codeset][@modifier]"
 +    or "C", where:
 +
 +    \list
 +    \o language is a lowercase, two-letter, ISO 639 language code,
 +    \o territory is an uppercase, two-letter, ISO 3166 country code,
 +    \o and codeset and modifier are ignored.
 +    \endlist
 +
 +    If the string violates the locale format, or language is not a
 +    valid ISO 369 code, the "C" locale is used instead. If country
 +    is not present, or is not a valid ISO 3166 code, the most
 +    appropriate country is chosen for the specified language.
 +
 +    \sa QtQuick2::Locale
 +*/
 +v8::Handle<v8::Value> locale(const v8::Arguments &args)
 +{
 +    QString code;
 +    if (args.Length() > 1)
 +        V8THROW_ERROR("locale() requires 0 or 1 argument");
 +    if (args.Length() == 1 && !args[0]->IsString())
 +        V8THROW_TYPE("locale(): argument (locale code) must be a string");
 +
 +    QV8Engine *v8engine = V8ENGINE();
 +    if (args.Length() == 1)
 +        code = v8engine->toString(args[0]);
 +
 +    return QQmlLocale::locale(v8engine, code);
 +}
 +
 +} // namespace QQmlBuiltinFunctions
 +
 +QT_END_NAMESPACE
index fdbf2f0,0000000..d4acc45
mode 100644,000000..100644
--- /dev/null
@@@ -1,43 -1,0 +1,61 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $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.
 +//
 +
 +#ifndef QSCRIPT_IMPL_P_H
 +#define QSCRIPT_IMPL_P_H
 +
 +#include "qv8engine_impl_p.h"
 +#include "qjsvalue_impl_p.h"
 +#include "qjsvalueiterator_impl_p.h"
 +#include "qjsconverter_impl_p.h"
 +
 +#endif //QSCRIPT_IMPL_P_H
index 4afa747,0000000..7784855
mode 100644,000000..100644
--- /dev/null
@@@ -1,71 -1,0 +1,89 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef APIPREAMBLE_P_H
 +#define APIPREAMBLE_P_H
 +
 +#include <private/qv8_p.h>
 +#include "qv8engine_p.h"
 +
 +QT_BEGIN_NAMESPACE
 +
 +/**
 +  \internal
 +  Class used to switch to the right isolate. It does the same thing as v8::Isolate::Scope but
 +  it checks for a null engine.
 +  \attention We decided to put context switching "up" which means that it should be as high
 +  as possible on call stack. And it should be switched at most once per public API function call.
 +*/
 +class QScriptIsolate {
 +public:
 +    // OperationMode was introduced to reduce number of checking for a null engine pointer. If we
 +    // know that given pointer is not null than we should pass NotNullEngine as constructor argument
 +    // that would nicely remove checking on compilation time.
 +    enum OperationMode {Default, NotNullEngine};
 +    inline QScriptIsolate(const QV8Engine *engine, const OperationMode mode = Default)
 +        : m_engine(engine)
 +        , m_mode(mode)
 +    {
 +        if (m_mode == NotNullEngine || m_engine) {
 +            Q_ASSERT(m_engine);
 +            m_engine->context()->Enter();
 +        }
 +    }
 +
 +    inline ~QScriptIsolate()
 +    {
 +        if (m_mode == NotNullEngine || m_engine) {
 +            m_engine->context()->Exit();
 +        }
 +    }
 +
 +private:
 +    Q_DISABLE_COPY(QScriptIsolate);
 +    const QV8Engine *m_engine;
 +    const OperationMode m_mode;
 +};
 +
 +
 +QT_END_NAMESPACE
 +
 +#endif // APIPREAMBLE_P_H
index 12321cc,0000000..e4661c1
mode 100644,000000..100644
--- /dev/null
@@@ -1,159 -1,0 +1,177 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QSCRIPTORIGINALGLOBALOBJECT_P_H
 +#define QSCRIPTORIGINALGLOBALOBJECT_P_H
 +
 +#include "QtCore/qglobal.h"
 +#include "qjsvalue_p.h"
 +
 +#include <private/qv8_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QV8Engine;
 +
 +/*!
 +    \internal
 +    This class is a workaround for missing V8 API functionality. This class keeps all important
 +    properties of an original (default) global object, so we can use it even if the global object was
 +    changed.
 +
 +    FIXME this class is a container for workarounds :-) it should be replaced by proper API calls.
 +
 +    The class have to be created on the QV8Engine creation time (before any change got applied to
 +    global object).
 +
 +    \attention All methods (apart from constructor) assumes that a context and a scope are prepared correctly.
 +*/
 +class QScriptOriginalGlobalObject
 +{
 +public:
 +    inline QScriptOriginalGlobalObject() {}
 +    inline void init(v8::Handle<v8::Context> context);
 +    inline void destroy();
 +
 +    inline QJSValuePrivate::PropertyFlags getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property);
 +    inline v8::Local<v8::Object> getOwnPropertyDescriptor(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) const;
 +    inline bool strictlyEquals(v8::Handle<v8::Object> object);
 +private:
 +    Q_DISABLE_COPY(QScriptOriginalGlobalObject)
 +
 +    // Copy of constructors and prototypes used in isType functions.
 +    v8::Persistent<v8::Function> m_ownPropertyDescriptor;
 +    v8::Persistent<v8::Object> m_globalObject;
 +};
 +
 +void QScriptOriginalGlobalObject::init(v8::Handle<v8::Context> context)
 +{
 +    // Please notice that engine is not fully initialized at this point.
 +
 +    v8::Context::Scope contextScope(context);
 +
 +    v8::HandleScope scope;
 +
 +    m_globalObject = v8::Persistent<v8::Object>::New(context->Global());
 +
 +    v8::Local<v8::Object> objectConstructor = m_globalObject->Get(v8::String::New("Object"))->ToObject();
 +    Q_ASSERT(objectConstructor->IsObject());
 +    {   // Initialize m_ownPropertyDescriptor.
 +        v8::Local<v8::Value> ownPropertyDescriptor = objectConstructor->Get(v8::String::New("getOwnPropertyDescriptor"));
 +        Q_ASSERT(!ownPropertyDescriptor.IsEmpty());
 +        m_ownPropertyDescriptor = v8::Persistent<v8::Function>::New(v8::Local<v8::Function>::Cast(ownPropertyDescriptor));
 +    }
 +}
 +
 +/*!
 +    \internal
 +    QScriptOriginalGlobalObject lives as long as QV8Engine that keeps it. In ~QSEP
 +    the v8 context is removed, so we need to remove our handlers before. to break this dependency
 +    destroy method should be called before or insight QSEP destructor.
 +*/
 +inline void QScriptOriginalGlobalObject::destroy()
 +{
 +    m_ownPropertyDescriptor.Dispose();
 +    m_globalObject.Dispose();
 +    // After this line this instance is unusable.
 +}
 +
 +inline QJSValuePrivate::PropertyFlags QScriptOriginalGlobalObject::getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property)
 +{
 +    Q_ASSERT(object->IsObject());
 +    Q_ASSERT(!property.IsEmpty());
 +    v8::Local<v8::Object> descriptor = getOwnPropertyDescriptor(object, property);
 +    if (descriptor.IsEmpty()) {
 +//        // Property isn't owned by this object.
 +//        if (!(mode & QScriptValue::ResolvePrototype))
 +//            return 0;
 +        v8::Local<v8::Value> prototype = object->GetPrototype();
 +        if (prototype->IsNull())
 +            return 0;
 +        return getPropertyFlags(v8::Local<v8::Object>::Cast(prototype), property);
 +    }
 +    v8::Local<v8::String> writableName = v8::String::New("writable");
 +    v8::Local<v8::String> configurableName = v8::String::New("configurable");
 +    v8::Local<v8::String> enumerableName = v8::String::New("enumerable");
 +//    v8::Local<v8::String> getName = v8::String::New("get");
 +//    v8::Local<v8::String> setName = v8::String::New("set");
 +
 +    unsigned flags = 0;
 +
 +    if (!descriptor->Get(configurableName)->BooleanValue())
 +        flags |= QJSValuePrivate::Undeletable;
 +    if (!descriptor->Get(enumerableName)->BooleanValue())
 +        flags |= QJSValuePrivate::SkipInEnumeration;
 +
 +    //"writable" is only a property of the descriptor if it is not an accessor
 +    if (descriptor->Has(writableName)) {
 +        if (!descriptor->Get(writableName)->BooleanValue())
 +            flags |= QJSValuePrivate::ReadOnly;
 +    } else {
 +//        if (descriptor->Get(getName)->IsObject())
 +//            flags |= QScriptValue::PropertyGetter;
 +//        if (descriptor->Get(setName)->IsObject())
 +//            flags |= QScriptValue::PropertySetter;
 +    }
 +
 +    return QJSValuePrivate::PropertyFlag(flags);
 +}
 +
 +inline v8::Local<v8::Object> QScriptOriginalGlobalObject::getOwnPropertyDescriptor(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) const
 +{
 +    Q_ASSERT(object->IsObject());
 +    Q_ASSERT(!property.IsEmpty());
 +    // FIXME do we need try catch here?
 +    v8::Handle<v8::Value> argv[] = {object, property};
 +    v8::Local<v8::Value> descriptor = m_ownPropertyDescriptor->Call(m_globalObject, /* argc */ 2, argv);
 +    if (descriptor.IsEmpty() || !descriptor->IsObject())
 +        return v8::Local<v8::Object>();
 +    return v8::Local<v8::Object>::Cast(descriptor);
 +}
 +
 +inline bool QScriptOriginalGlobalObject::strictlyEquals(v8::Handle<v8::Object> object)
 +{
 +    return m_globalObject->GetPrototype()->StrictEquals(object);
 +}
 +
 +QT_END_NAMESPACE
 +
 +#endif
index df95b26,0000000..d3491c7
mode 100644,000000..100644
--- /dev/null
@@@ -1,151 -1,0 +1,169 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $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.
 +//
 +
 +#ifndef QSCRIPTSHAREDDATA_P_H
 +#define QSCRIPTSHAREDDATA_P_H
 +
 +#include "qglobal.h"
 +#include "qshareddata.h"
 +
 +QT_BEGIN_NAMESPACE
 +
 +/*!
 +  \internal
 +  This class should have the same interface as the QSharedData, but implementation doesn't
 +  need to be thread safe, so atomic ref count was replaced by normal integer value.
 +*/
 +class QScriptSharedData
 +{
 +public:
 +    class ReferenceCounter {
 +        // FIXME shouldn't it be uint or something longer?
 +        mutable int m_ref;
 +        ReferenceCounter(int ref) : m_ref(ref) {}
 +        ~ReferenceCounter() { Q_ASSERT_X(!m_ref, Q_FUNC_INFO, "Memory problem found"); }
 +    public:
 +        bool ref() { return ++m_ref; }
 +        bool deref() { return --m_ref; }
 +        friend class QScriptSharedData;
 +    };
 +
 +    ReferenceCounter ref;
 +    inline QScriptSharedData() : ref(0) { }
 +
 +private:
 +    Q_DISABLE_COPY(QScriptSharedData)
 +};
 +
 +
 +template <class T> class QScriptPassPointer;
 +
 +// FIXME: that could be reimplemented to not check for a null value.
 +template<class T>
 +class QScriptSharedDataPointer : public QExplicitlySharedDataPointer<T>
 +{
 +public:
 +    inline QScriptSharedDataPointer() {}
 +    explicit QScriptSharedDataPointer(QScriptPassPointer<T> data) : QExplicitlySharedDataPointer<T>(data.give()) {}
 +    explicit QScriptSharedDataPointer(T *data) : QExplicitlySharedDataPointer<T>(data) {}
 +
 +    inline QScriptSharedDataPointer<T> &operator=(const QScriptPassPointer<T> &other)
 +    {
 +        this->QExplicitlySharedDataPointer<T>::operator =(other.give());
 +        return *this;
 +    }
 +    inline QScriptSharedDataPointer<T> &operator=(T *other)
 +    {
 +        this->QExplicitlySharedDataPointer<T>::operator =(other);
 +        return *this;
 +    }
 +};
 +
 +// FIXME: that could be reimplemented to not check for a null value.
 +template <class T>
 +class QScriptPassPointer {
 +public:
 +    QScriptPassPointer(T *data) : m_ptr(data) {}
 +    inline QScriptPassPointer() { m_ptr = 0; }
 +    inline QScriptPassPointer(const QScriptPassPointer<T> &other) : m_ptr(other.give()) {}
 +    inline ~QScriptPassPointer() { Q_ASSERT_X(!m_ptr, Q_FUNC_INFO, "Ownership of the QScriptPassPointer hasn't been taken"); }
 +
 +    inline T &operator*() const { return *m_ptr; }
 +    inline T *operator->() { return m_ptr; }
 +    inline T *operator->() const { return m_ptr; }
 +    inline T *data() const { return m_ptr; }
 +    inline const T *constData() const { return m_ptr; }
 +
 +    inline bool operator==(const QScriptPassPointer<T> &other) const { return m_ptr == other.m_ptr; }
 +    inline bool operator!=(const QScriptPassPointer<T> &other) const { return m_ptr != other.m_ptr; }
 +    inline bool operator==(const QScriptSharedDataPointer<T> &other) const { return m_ptr == other.m_ptr; }
 +    inline bool operator!=(const QScriptSharedDataPointer<T> &other) const { return m_ptr != other.m_ptr; }
 +    inline bool operator==(const T *ptr) const { return m_ptr == ptr; }
 +    inline bool operator!=(const T *ptr) const { return m_ptr != ptr; }
 +
 +    inline operator bool () const { return m_ptr != 0; }
 +    inline bool operator!() const { return !m_ptr; }
 +
 +    inline QScriptPassPointer<T> & operator=(const QScriptPassPointer<T> &other)
 +    {
 +        if (other.m_ptr != m_ptr) {
 +            if (m_ptr)
 +                delete m_ptr;
 +            m_ptr = other.give();
 +        }
 +        return *this;
 +    }
 +
 +    inline QScriptPassPointer &operator=(T *other)
 +    {
 +        if (other != m_ptr) {
 +            if (m_ptr)
 +                delete m_ptr;
 +            m_ptr = other;
 +        }
 +        return *this;
 +    }
 +
 +    inline T* give() const
 +    {
 +        T* result = m_ptr;
 +        m_ptr = 0;
 +        return result;
 +    }
 +
 +private:
 +    mutable T* m_ptr;
 +};
 +
 +QT_END_NAMESPACE
 +
 +#endif // QSCRIPTSHAREDDATA_P_H
index fcea205,0000000..d69e9c8
mode 100644,000000..100644
--- /dev/null
@@@ -1,68 -1,0 +1,86 @@@
- ** This file is part of the QtScript module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $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.
 +//
 +
 +
 +#ifndef QSCRIPTTOOLS_P_H
 +#define QSCRIPTTOOLS_P_H
 +
 +#include <private/qintrusivelist_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +template<class N, QIntrusiveListNode N::*member>
 +class QScriptIntrusiveList : public QIntrusiveList<N, member>
 +{
 +public:
 +    inline void insert(N *n);
 +    inline void remove(N *n);
 +};
 +
 +template<class N, QIntrusiveListNode N::*member>
 +void QScriptIntrusiveList<N, member>::insert(N *n)
 +{
 +    Q_ASSERT_X(!this->contains(n), Q_FUNC_INFO, "Can't insert a value which is in the list already");
 +    Q_ASSERT_X(!(n->*member).isInList(), Q_FUNC_INFO, "Can't insert a value which is in another list");
 +    QIntrusiveList<N, member>::insert(n);
 +}
 +
 +template<class N, QIntrusiveListNode N::*member>
 +void QScriptIntrusiveList<N, member>::remove(N *n)
 +{
 +    Q_ASSERT_X(this->contains(n), Q_FUNC_INFO, "Can't remove a value which is not in the list");
 +    QIntrusiveList<N, member>::remove(n);
 +}
 +
 +QT_END_NAMESPACE
 +
 +#endif //QSCRIPTTOOLS_P_H
index 4c2cce1,0000000..8e8223f
mode 100644,000000..100644
--- /dev/null
@@@ -1,1598 -1,0 +1,1600 @@@
-     Q_ASSERT(lhsr->engine == rhsr->engine);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qv8engine_p.h"
 +
 +#include <QtGui/QGuiApplication>
 +
 +#include "qv8contextwrapper_p.h"
 +#include "qv8valuetypewrapper_p.h"
 +#include "qv8sequencewrapper_p.h"
 +#include "qv8include_p.h"
 +#include "qjsengine_p.h"
 +#include "../../../3rdparty/javascriptcore/DateMath.h"
 +
 +#include <private/qqmlbuiltinfunctions_p.h>
 +#include <private/qqmllist_p.h>
 +#include <private/qqmlengine_p.h>
 +#include <private/qquickapplication_p.h>
 +#include <private/qqmlxmlhttprequest_p.h>
 +#include <private/qqmllocale_p.h>
 +
 +#include "qscript_impl_p.h"
 +#include "qv8domerrors_p.h"
 +#include "qv8sqlerrors_p.h"
 +
 +
 +Q_DECLARE_METATYPE(QJSValue)
 +Q_DECLARE_METATYPE(QList<int>)
 +
 +
 +// XXX TODO: Need to check all the global functions will also work in a worker script where the 
 +// QQmlEngine is not available
 +QT_BEGIN_NAMESPACE
 +
 +static bool ObjectComparisonCallback(v8::Local<v8::Object> lhs, v8::Local<v8::Object> rhs)
 +{
 +    if (lhs == rhs)
 +        return true;
 +
++    if (lhs.IsEmpty() || rhs.IsEmpty())
++        return false;
++
 +    QV8ObjectResource *lhsr = static_cast<QV8ObjectResource*>(lhs->GetExternalResource());
 +    QV8ObjectResource *rhsr = static_cast<QV8ObjectResource*>(rhs->GetExternalResource());
 +
- void QV8Engine::initDeclarativeGlobalObject()
 +    if (lhsr && rhsr) {
++        Q_ASSERT(lhsr->engine == rhsr->engine);
 +        QV8ObjectResource::ResourceType lhst = lhsr->resourceType();
 +        QV8ObjectResource::ResourceType rhst = rhsr->resourceType();
 +
 +        switch (lhst) {
 +        case QV8ObjectResource::ValueTypeType:
 +            // a value type might be equal to a variant or another value type
 +            if (rhst == QV8ObjectResource::ValueTypeType) {
 +                return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, lhsr->engine->valueTypeWrapper()->toVariant(rhsr));
 +            } else if (rhst == QV8ObjectResource::VariantType) {
 +                return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, lhsr->engine->variantWrapper()->toVariant(rhsr));
 +            }
 +            break;
 +        case QV8ObjectResource::VariantType:
 +            // a variant might be equal to a value type or other variant.
 +            if (rhst == QV8ObjectResource::VariantType) {
 +                return lhsr->engine->variantWrapper()->toVariant(lhsr) == 
 +                       lhsr->engine->variantWrapper()->toVariant(rhsr);
 +            } else if (rhst == QV8ObjectResource::ValueTypeType) {
 +                return rhsr->engine->valueTypeWrapper()->isEqual(rhsr, rhsr->engine->variantWrapper()->toVariant(lhsr));
 +            }
 +            break;
 +        case QV8ObjectResource::SequenceType:
 +            // a sequence might be equal to itself.
 +            if (rhst == QV8ObjectResource::SequenceType) {
 +                return lhsr->engine->sequenceWrapper()->isEqual(lhsr, rhsr);
 +            }
 +            break;
 +        default:
 +            break;
 +        }
 +    }
 +
 +    return false;
 +}
 +
 +
 +QV8Engine::QV8Engine(QJSEngine* qq, QJSEngine::ContextOwnership ownership)
 +    : q(qq)
 +    , m_engine(0)
 +    , m_ownsV8Context(ownership == QJSEngine::CreateNewContext)
 +    , m_xmlHttpRequestData(0)
 +    , m_listModelData(0)
 +{
 +    qMetaTypeId<QJSValue>();
 +    qMetaTypeId<QList<int> >();
 +
 +    QByteArray v8args = qgetenv("V8ARGS");
 +    // change default v8 behaviour to not relocate breakpoints across lines
 +    if (!v8args.contains("breakpoint_relocation"))
 +        v8args.append(" --nobreakpoint_relocation");
 +    v8::V8::SetFlagsFromString(v8args.constData(), v8args.length());
 +
 +    ensurePerThreadIsolate();
 +
 +    v8::HandleScope handle_scope;
 +    m_context = (ownership == QJSEngine::CreateNewContext) ? v8::Context::New() : v8::Persistent<v8::Context>::New(v8::Context::GetCurrent());
 +    qPersistentRegister(m_context);
 +    m_originalGlobalObject.init(m_context);
 +    v8::Context::Scope context_scope(m_context);
 +
 +    v8::V8::SetUserObjectComparisonCallbackFunction(ObjectComparisonCallback);
 +    QV8GCCallback::registerGcPrologueCallback();
 +    m_strongReferencer = qPersistentNew(v8::Object::New());
 +
 +    m_stringWrapper.init();
 +    m_contextWrapper.init(this);
 +    m_qobjectWrapper.init(this);
 +    m_typeWrapper.init(this);
 +    m_listWrapper.init(this);
 +    m_variantWrapper.init(this);
 +    m_valueTypeWrapper.init(this);
 +    m_sequenceWrapper.init(this);
 +
 +    {
 +    v8::Handle<v8::Value> v = global()->Get(v8::String::New("Object"))->ToObject()->Get(v8::String::New("getOwnPropertyNames"));
 +    m_getOwnPropertyNames = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(v));
 +    }
 +}
 +
 +QV8Engine::~QV8Engine()
 +{
 +    Q_ASSERT_X(v8::Isolate::GetCurrent(), "QV8Engine::~QV8Engine()", "called after v8::Isolate has exited");
 +    for (int ii = 0; ii < m_extensionData.count(); ++ii) 
 +        delete m_extensionData[ii];
 +    m_extensionData.clear();
 +
 +    qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
 +    m_xmlHttpRequestData = 0;
 +    delete m_listModelData;
 +    m_listModelData = 0;
 +
 +    qPersistentDispose(m_freezeObject);
 +    qPersistentDispose(m_getOwnPropertyNames);
 +
 +    invalidateAllValues();
 +    clearExceptions();
 +
 +    qPersistentDispose(m_strongReferencer);
 +
 +    m_sequenceWrapper.destroy();
 +    m_valueTypeWrapper.destroy();
 +    m_variantWrapper.destroy();
 +    m_listWrapper.destroy();
 +    m_typeWrapper.destroy();
 +    m_qobjectWrapper.destroy();
 +    m_contextWrapper.destroy();
 +    m_stringWrapper.destroy();
 +
 +    m_originalGlobalObject.destroy();
 +
 +    if (m_ownsV8Context)
 +        qPersistentDispose(m_context);
 +}
 +
 +QString QV8Engine::toStringStatic(v8::Handle<v8::Value> jsstr)
 +{
 +    return toStringStatic(jsstr->ToString());
 +}
 +
 +QString QV8Engine::toStringStatic(v8::Handle<v8::String> jsstr)
 +{
 +    QString qstr;
 +    qstr.resize(jsstr->Length());
 +    jsstr->Write((uint16_t*)qstr.data());
 +    return qstr;
 +}
 +
 +QVariant QV8Engine::toVariant(v8::Handle<v8::Value> value, int typeHint)
 +{
 +    if (value.IsEmpty()) 
 +        return QVariant();
 +
 +    if (typeHint == QVariant::Bool)
 +        return QVariant(value->BooleanValue());
 +
 +    if (value->IsObject()) {
 +        QV8ObjectResource *r = (QV8ObjectResource *)value->ToObject()->GetExternalResource();
 +        if (r) {
 +            switch (r->resourceType()) {
 +            case QV8ObjectResource::Context2DStyleType:
 +            case QV8ObjectResource::Context2DPixelArrayType:
 +            case QV8ObjectResource::SignalHandlerType:
 +            case QV8ObjectResource::IncubatorType:
 +            case QV8ObjectResource::VisualDataItemType:
 +            case QV8ObjectResource::ContextType:
 +            case QV8ObjectResource::XMLHttpRequestType:
 +            case QV8ObjectResource::DOMNodeType:
 +            case QV8ObjectResource::SQLDatabaseType:
 +            case QV8ObjectResource::ListModelType:
 +            case QV8ObjectResource::Context2DType:
 +            case QV8ObjectResource::ParticleDataType:
 +            case QV8ObjectResource::LocaleDataType:
 +                return QVariant();
 +            case QV8ObjectResource::TypeType:
 +                return m_typeWrapper.toVariant(r);
 +            case QV8ObjectResource::QObjectType:
 +                return qVariantFromValue<QObject *>(m_qobjectWrapper.toQObject(r));
 +            case QV8ObjectResource::ListType:
 +                return m_listWrapper.toVariant(r);
 +            case QV8ObjectResource::VariantType:
 +                return m_variantWrapper.toVariant(r);
 +            case QV8ObjectResource::ValueTypeType:
 +                return m_valueTypeWrapper.toVariant(r);
 +            case QV8ObjectResource::SequenceType:
 +                return m_sequenceWrapper.toVariant(r);
 +            }
 +        }
 +    }
 +
 +    if (value->IsArray()) {
 +        v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
 +        if (typeHint == qMetaTypeId<QList<QObject *> >()) {
 +            QList<QObject *> list;
 +            uint32_t length = array->Length();
 +            for (uint32_t ii = 0; ii < length; ++ii) {
 +                v8::Local<v8::Value> arrayItem = array->Get(ii);
 +                if (arrayItem->IsObject()) {
 +                    list << toQObject(arrayItem->ToObject());
 +                } else {
 +                    list << 0;
 +                }
 +            }
 +
 +            return qVariantFromValue<QList<QObject*> >(list);
 +        }
 +
 +        bool succeeded = false;
 +        QVariant retn = m_sequenceWrapper.toVariant(array, typeHint, &succeeded);
 +        if (succeeded)
 +            return retn;
 +    }
 +
 +    return toBasicVariant(value);
 +}
 +
 +static v8::Handle<v8::Array> arrayFromStringList(QV8Engine *engine, const QStringList &list)
 +{
 +    v8::Context::Scope scope(engine->context());
 +    v8::Local<v8::Array> result = v8::Array::New(list.count());
 +    for (int ii = 0; ii < list.count(); ++ii)
 +        result->Set(ii, engine->toString(list.at(ii)));
 +    return result;
 +}
 +
 +static v8::Handle<v8::Array> arrayFromVariantList(QV8Engine *engine, const QVariantList &list)
 +{
 +    v8::Context::Scope scope(engine->context());
 +    v8::Local<v8::Array> result = v8::Array::New(list.count());
 +    for (int ii = 0; ii < list.count(); ++ii)
 +        result->Set(ii, engine->fromVariant(list.at(ii)));
 +    return result;
 +}
 +
 +static v8::Handle<v8::Object> objectFromVariantMap(QV8Engine *engine, const QVariantMap &map)
 +{
 +    v8::Context::Scope scope(engine->context());
 +    v8::Local<v8::Object> object = v8::Object::New();
 +    for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter) 
 +        object->Set(engine->toString(iter.key()), engine->fromVariant(iter.value()));
 +    return object;
 +}
 +
 +Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
 +
 +v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant)
 +{
 +    int type = variant.userType();
 +    const void *ptr = variant.constData();
 +
 +    if (type < QMetaType::User) {
 +        switch (QMetaType::Type(type)) {
 +            case QMetaType::Void:
 +                return v8::Undefined();
 +            case QMetaType::Bool:
 +                return v8::Boolean::New(*reinterpret_cast<const bool*>(ptr));
 +            case QMetaType::Int:
 +                return v8::Integer::New(*reinterpret_cast<const int*>(ptr));
 +            case QMetaType::UInt:
 +                return v8::Integer::NewFromUnsigned(*reinterpret_cast<const uint*>(ptr));
 +            case QMetaType::LongLong:
 +                return v8::Number::New(*reinterpret_cast<const qlonglong*>(ptr));
 +            case QMetaType::ULongLong:
 +                return v8::Number::New(*reinterpret_cast<const qulonglong*>(ptr));
 +            case QMetaType::Double:
 +                return v8::Number::New(*reinterpret_cast<const double*>(ptr));
 +            case QMetaType::QString:
 +                return m_stringWrapper.toString(*reinterpret_cast<const QString*>(ptr));
 +            case QMetaType::Float:
 +                return v8::Number::New(*reinterpret_cast<const float*>(ptr));
 +            case QMetaType::Short:
 +                return v8::Integer::New(*reinterpret_cast<const short*>(ptr));
 +            case QMetaType::UShort:
 +                return v8::Integer::NewFromUnsigned(*reinterpret_cast<const unsigned short*>(ptr));
 +            case QMetaType::Char:
 +                return v8::Integer::New(*reinterpret_cast<const char*>(ptr));
 +            case QMetaType::UChar:
 +                return v8::Integer::NewFromUnsigned(*reinterpret_cast<const unsigned char*>(ptr));
 +            case QMetaType::QChar:
 +                return v8::Integer::New((*reinterpret_cast<const QChar*>(ptr)).unicode());
 +            case QMetaType::QDateTime:
 +                return v8::Date::New(qtDateTimeToJsDate(*reinterpret_cast<const QDateTime *>(ptr)));
 +            case QMetaType::QDate:
 +                return v8::Date::New(qtDateTimeToJsDate(QDateTime(*reinterpret_cast<const QDate *>(ptr))));
 +            case QMetaType::QTime:
 +                return v8::Date::New(qtDateTimeToJsDate(QDateTime(QDate(1970,1,1), *reinterpret_cast<const QTime *>(ptr))));
 +            case QMetaType::QRegExp:
 +                return QJSConverter::toRegExp(*reinterpret_cast<const QRegExp *>(ptr));
 +            case QMetaType::QObjectStar:
 +            case QMetaType::QWidgetStar:
 +                return newQObject(*reinterpret_cast<QObject* const *>(ptr));
 +            case QMetaType::QStringList:
 +                {
 +                bool succeeded = false;
 +                v8::Handle<v8::Value> retn = m_sequenceWrapper.fromVariant(variant, &succeeded);
 +                if (succeeded)
 +                    return retn;
 +                return arrayFromStringList(this, *reinterpret_cast<const QStringList *>(ptr));
 +                }
 +            case QMetaType::QVariantList:
 +                return arrayFromVariantList(this, *reinterpret_cast<const QVariantList *>(ptr));
 +            case QMetaType::QVariantMap:
 +                return objectFromVariantMap(this, *reinterpret_cast<const QVariantMap *>(ptr));
 +
 +            default:
 +                break;
 +        }
 +
 +        if (m_engine) {
 +            if (QQmlValueType *vt = QQmlEnginePrivate::get(m_engine)->valueTypes[type])
 +                return m_valueTypeWrapper.newValueType(variant, vt);
 +        }
 +
 +    } else {
 +        if (type == qMetaTypeId<QQmlListReference>()) {
 +            typedef QQmlListReferencePrivate QDLRP;
 +            QDLRP *p = QDLRP::get((QQmlListReference*)ptr);
 +            if (p->object) {
 +                return m_listWrapper.newList(p->property, p->propertyType);
 +            } else {
 +                return v8::Null();
 +            }
 +        } else if (type == qMetaTypeId<QJSValue>()) {
 +            const QJSValue *value = reinterpret_cast<const QJSValue *>(ptr);
 +            QJSValuePrivate *valuep = QJSValuePrivate::get(*value);
 +            if (valuep->assignEngine(this))
 +                return v8::Local<v8::Value>::New(*valuep);
 +        } else if (type == qMetaTypeId<QList<QObject *> >()) {
 +            // XXX Can this be made more by using Array as a prototype and implementing
 +            // directly against QList<QObject*>?
 +            const QList<QObject *> &list = *(QList<QObject *>*)ptr;
 +            v8::Local<v8::Array> array = v8::Array::New(list.count());
 +            for (int ii = 0; ii < list.count(); ++ii) 
 +                array->Set(ii, newQObject(list.at(ii)));
 +            return array;
 +        } 
 +
 +        bool objOk;
 +        QObject *obj = QQmlMetaType::toQObject(variant, &objOk);
 +        if (objOk) 
 +            return newQObject(obj);
 +
 +        bool succeeded = false;
 +        v8::Handle<v8::Value> retn = m_sequenceWrapper.fromVariant(variant, &succeeded);
 +        if (succeeded)
 +            return retn;
 +    }
 +
 +    // XXX TODO: To be compatible, we still need to handle:
 +    //    + QObjectList
 +    //    + QList<int>
 +
 +    return m_variantWrapper.newVariant(variant);
 +}
 +
 +// A handle scope and context must be entered
 +v8::Local<v8::Script> QV8Engine::qmlModeCompile(const QString &source,
 +                                                const QString &fileName,
 +                                                int lineNumber)
 +{
 +    v8::Local<v8::String> v8source = m_stringWrapper.toString(source);
 +    v8::Local<v8::String> v8fileName = m_stringWrapper.toString(fileName);
 +
 +    v8::ScriptOrigin origin(v8fileName, v8::Integer::New(lineNumber - 1));
 +
 +    v8::Local<v8::Script> script = v8::Script::Compile(v8source, &origin, 0, v8::Handle<v8::String>(), 
 +                                                       v8::Script::QmlMode);
 +
 +    return script;
 +}
 +
 +// A handle scope and context must be entered.
 +// source can be either ascii or utf8.
 +v8::Local<v8::Script> QV8Engine::qmlModeCompile(const char *source, int sourceLength,
 +                                                const QString &fileName,
 +                                                int lineNumber)
 +{
 +    if (sourceLength == -1)
 +        sourceLength = strlen(source);
 +
 +    v8::Local<v8::String> v8source = v8::String::New(source, sourceLength);
 +    v8::Local<v8::String> v8fileName = m_stringWrapper.toString(fileName);
 +
 +    v8::ScriptOrigin origin(v8fileName, v8::Integer::New(lineNumber - 1));
 +
 +    v8::Local<v8::Script> script = v8::Script::Compile(v8source, &origin, 0, v8::Handle<v8::String>(),
 +                                                       v8::Script::QmlMode);
 +
 +    return script;
 +}
 +
 +QNetworkAccessManager *QV8Engine::networkAccessManager() 
 +{
 +    return QQmlEnginePrivate::get(m_engine)->getNetworkAccessManager();
 +}
 +
 +const QStringHash<bool> &QV8Engine::illegalNames() const
 +{
 +    return m_illegalNames;
 +}
 +
 +// Requires a handle scope
 +v8::Local<v8::Array> QV8Engine::getOwnPropertyNames(v8::Handle<v8::Object> o)
 +{
 +    // FIXME Newer v8 have API for this function
 +    v8::TryCatch tc;
 +    v8::Handle<v8::Value> args[] = { o };
 +    v8::Local<v8::Value> r = m_getOwnPropertyNames->Call(global(), 1, args);
 +    if (tc.HasCaught())
 +        return v8::Array::New();
 +    else
 +        return v8::Local<v8::Array>::Cast(r);
 +}
 +
 +QQmlContextData *QV8Engine::callingContext()
 +{
 +    return m_contextWrapper.callingContext();
 +}
 +
 +// Converts a JS value to a QVariant.
 +// Null, Undefined -> QVariant() (invalid)
 +// Boolean -> QVariant(bool)
 +// Number -> QVariant(double)
 +// String -> QVariant(QString)
 +// Array -> QVariantList(...)
 +// Date -> QVariant(QDateTime)
 +// RegExp -> QVariant(QRegExp)
 +// [Any other object] -> QVariantMap(...)
 +QVariant QV8Engine::toBasicVariant(v8::Handle<v8::Value> value)
 +{
 +    if (value->IsNull() || value->IsUndefined())
 +        return QVariant();
 +    if (value->IsBoolean())
 +        return value->ToBoolean()->Value();
 +    if (value->IsInt32())
 +        return value->ToInt32()->Value();
 +    if (value->IsNumber())
 +        return value->ToNumber()->Value();
 +    if (value->IsString())
 +        return m_stringWrapper.toString(value->ToString());
 +    if (value->IsDate())
 +        return qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(value)->NumberValue());
 +    // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
 +
 +    Q_ASSERT(value->IsObject());
 +
 +    if (value->IsRegExp()) {
 +        v8::Context::Scope scope(context());
 +        return QJSConverter::toRegExp(v8::Handle<v8::RegExp>::Cast(value));
 +    }
 +    if (value->IsArray()) {
 +        v8::Context::Scope scope(context());
 +        QVariantList rv;
 +
 +        v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
 +        int length = array->Length();
 +        for (int ii = 0; ii < length; ++ii)
 +            rv << toVariant(array->Get(ii), -1);
 +        return rv;
 +    }
 +    if (!value->IsFunction()) {
 +        v8::Context::Scope scope(context());
 +        v8::Handle<v8::Object> object = value->ToObject();
 +        return variantMapFromJS(object);
 +    }
 +
 +    return QVariant();
 +}
 +
 +
 +
 +#include <QtGui/qvector3d.h>
 +#include <QtGui/qvector4d.h>
 +
 +struct StaticQtMetaObject : public QObject
 +{
 +    static const QMetaObject *get()
 +        { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
 +};
 +
 +void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
 +{
 +    using namespace QQmlBuiltinFunctions;
 +
 +    v8::Local<v8::Object> console = v8::Object::New();
 +    v8::Local<v8::Function> consoleLogFn = V8FUNCTION(consoleLog, this);
 +
 +    console->Set(v8::String::New("debug"), consoleLogFn);
 +    console->Set(v8::String::New("log"), consoleLogFn);
 +    console->Set(v8::String::New("info"), consoleLogFn);
 +    console->Set(v8::String::New("warn"), V8FUNCTION(consoleWarn, this));
 +    console->Set(v8::String::New("error"), V8FUNCTION(consoleError, this));
 +    console->Set(v8::String::New("assert"), V8FUNCTION(consoleAssert, this));
 +
 +    console->Set(v8::String::New("count"), V8FUNCTION(consoleCount, this));
 +    console->Set(v8::String::New("profile"), V8FUNCTION(consoleProfile, this));
 +    console->Set(v8::String::New("profileEnd"), V8FUNCTION(consoleProfileEnd, this));
 +    console->Set(v8::String::New("time"), V8FUNCTION(consoleTime, this));
 +    console->Set(v8::String::New("timeEnd"), V8FUNCTION(consoleTimeEnd, this));
 +    console->Set(v8::String::New("trace"), V8FUNCTION(consoleTrace, this));
 +    console->Set(v8::String::New("exception"), V8FUNCTION(consoleException, this));
 +
 +    v8::Local<v8::Object> qt = v8::Object::New();
 +
 +    // Set all the enums from the "Qt" namespace
 +    const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
 +    for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
 +        QMetaEnum enumerator = qtMetaObject->enumerator(ii);
 +        for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
 +            qt->Set(v8::String::New(enumerator.key(jj)), v8::Integer::New(enumerator.value(jj)));
 +        }
 +    }
 +    qt->Set(v8::String::New("Asynchronous"), v8::Integer::New(0));
 +    qt->Set(v8::String::New("Synchronous"), v8::Integer::New(1));
 +
 +    qt->Set(v8::String::New("include"), V8FUNCTION(QV8Include::include, this));
 +    qt->Set(v8::String::New("isQtObject"), V8FUNCTION(isQtObject, this));
 +    qt->Set(v8::String::New("rgba"), V8FUNCTION(rgba, this));
 +    qt->Set(v8::String::New("hsla"), V8FUNCTION(hsla, this));
 +    qt->Set(v8::String::New("rect"), V8FUNCTION(rect, this));
 +    qt->Set(v8::String::New("point"), V8FUNCTION(point, this));
 +    qt->Set(v8::String::New("size"), V8FUNCTION(size, this));
 +    qt->Set(v8::String::New("vector3d"), V8FUNCTION(vector3d, this));
 +    qt->Set(v8::String::New("vector4d"), V8FUNCTION(vector4d, this));
 +
 +    qt->Set(v8::String::New("formatDate"), V8FUNCTION(formatDate, this));
 +    qt->Set(v8::String::New("formatTime"), V8FUNCTION(formatTime, this));
 +    qt->Set(v8::String::New("formatDateTime"), V8FUNCTION(formatDateTime, this));
 +
 +    qt->Set(v8::String::New("openUrlExternally"), V8FUNCTION(openUrlExternally, this));
 +    qt->Set(v8::String::New("fontFamilies"), V8FUNCTION(fontFamilies, this));
 +    qt->Set(v8::String::New("md5"), V8FUNCTION(md5, this));
 +    qt->Set(v8::String::New("btoa"), V8FUNCTION(btoa, this));
 +    qt->Set(v8::String::New("atob"), V8FUNCTION(atob, this));
 +    qt->Set(v8::String::New("resolvedUrl"), V8FUNCTION(resolvedUrl, this));
 +    qt->Set(v8::String::New("locale"), V8FUNCTION(locale, this));
 +
 +    if (m_engine) {
 +        qt->Set(v8::String::New("application"), newQObject(new QQuickApplication(m_engine)));
 +        qt->Set(v8::String::New("inputMethod"), newQObject(qGuiApp->inputMethod(), CppOwnership));
 +        qt->Set(v8::String::New("lighter"), V8FUNCTION(lighter, this));
 +        qt->Set(v8::String::New("darker"), V8FUNCTION(darker, this));
 +        qt->Set(v8::String::New("tint"), V8FUNCTION(tint, this));
 +        qt->Set(v8::String::New("quit"), V8FUNCTION(quit, this));
 +        qt->Set(v8::String::New("createQmlObject"), V8FUNCTION(createQmlObject, this));
 +        qt->Set(v8::String::New("createComponent"), V8FUNCTION(createComponent, this));
 +    }
 +
 +    global->Set(v8::String::New("qsTranslate"), V8FUNCTION(qsTranslate, this));
 +    global->Set(v8::String::New("QT_TRANSLATE_NOOP"), V8FUNCTION(qsTranslateNoOp, this));
 +    global->Set(v8::String::New("qsTr"), V8FUNCTION(qsTr, this));
 +    global->Set(v8::String::New("QT_TR_NOOP"), V8FUNCTION(qsTrNoOp, this));
 +    global->Set(v8::String::New("qsTrId"), V8FUNCTION(qsTrId, this));
 +    global->Set(v8::String::New("QT_TRID_NOOP"), V8FUNCTION(qsTrIdNoOp, this));
 +
 +    global->Set(v8::String::New("print"), consoleLogFn);
 +    global->Set(v8::String::New("console"), console);
 +    global->Set(v8::String::New("Qt"), qt);
 +    global->Set(v8::String::New("gc"), V8FUNCTION(QQmlBuiltinFunctions::gc, this));
 +
 +    {
 +#define STRING_ARG "(function(stringArg) { "\
 +                   "    String.prototype.arg = (function() {"\
 +                   "        return stringArg.apply(this, arguments);"\
 +                   "    })"\
 +                   "})"
 +
 +        v8::Local<v8::Script> registerArg = v8::Script::New(v8::String::New(STRING_ARG), 0, 0, v8::Handle<v8::String>(), v8::Script::NativeMode);
 +        v8::Local<v8::Value> result = registerArg->Run();
 +        Q_ASSERT(result->IsFunction());
 +        v8::Local<v8::Function> registerArgFunc = v8::Local<v8::Function>::Cast(result);
 +        v8::Handle<v8::Value> args = V8FUNCTION(stringArg, this);
 +        registerArgFunc->Call(v8::Local<v8::Object>::Cast(registerArgFunc), 1, &args);
 +#undef STRING_ARG
 +    }
 +
 +    QQmlLocale::registerStringLocaleCompare(this);
 +    QQmlDateExtension::registerExtension(this);
 +    QQmlNumberExtension::registerExtension(this);
 +
 +    qt_add_domexceptions(this);
 +    m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
 +
 +    qt_add_sqlexceptions(this);
 +
 +    {
 +    v8::Handle<v8::Value> args[] = { global };
 +    v8::Local<v8::Value> names = m_getOwnPropertyNames->Call(global, 1, args);
 +    v8::Local<v8::Array> namesArray = v8::Local<v8::Array>::Cast(names);
 +    for (quint32 ii = 0; ii < namesArray->Length(); ++ii) 
 +        m_illegalNames.insert(toString(namesArray->Get(ii)), true);
 +    }
 +
 +    {
 +#define FREEZE_SOURCE "(function freeze_recur(obj) { "\
 +                      "    if (Qt.isQtObject(obj)) return;"\
 +                      "    if (obj != Function.connect && obj != Function.disconnect && "\
 +                      "        obj instanceof Object) {"\
 +                      "        var properties = Object.getOwnPropertyNames(obj);"\
 +                      "        for (var prop in properties) { "\
 +                      "            if (prop == \"connect\" || prop == \"disconnect\") {"\
 +                      "                Object.freeze(obj[prop]); "\
 +                      "                continue;"\
 +                      "            }"\
 +                      "            freeze_recur(obj[prop]);"\
 +                      "        }"\
 +                      "    }"\
 +                      "    if (obj instanceof Object) {"\
 +                      "        Object.freeze(obj);"\
 +                      "    }"\
 +                      "})"
 +
 +    v8::Local<v8::Script> freeze = v8::Script::New(v8::String::New(FREEZE_SOURCE));
 +    v8::Local<v8::Value> result = freeze->Run();
 +    Q_ASSERT(result->IsFunction());
 +    m_freezeObject = qPersistentNew(v8::Local<v8::Function>::Cast(result));
 +#undef FREEZE_SOURCE
 +    }
 +}
 +
 +void QV8Engine::freezeObject(v8::Handle<v8::Value> value)
 +{
 +    v8::Handle<v8::Value> args[] = { value };
 +    m_freezeObject->Call(global(), 1, args);
 +}
 +
 +void QV8Engine::gc()
 +{
 +    v8::V8::LowMemoryNotification();
 +    while (!v8::V8::IdleNotification()) {}
 +}
 +
 +#ifdef QML_GLOBAL_HANDLE_DEBUGGING
 +#include <QtCore/qthreadstorage.h>
 +static QThreadStorage<QSet<void *> *> QV8Engine_activeHandles;
 +
 +void QV8Engine::registerHandle(void *handle)
 +{
 +    if (!handle) {
 +        qWarning("Attempting to register a null handle");
 +        return;
 +    }
 +
 +    if (!QV8Engine_activeHandles.hasLocalData()) 
 +        QV8Engine_activeHandles.setLocalData(new QSet<void *>);
 +
 +    if (QV8Engine_activeHandles.localData()->contains(handle)) {
 +        qFatal("Handle %p already alive", handle);
 +    } else {
 +        QV8Engine_activeHandles.localData()->insert(handle);
 +    }
 +}
 +
 +void QV8Engine::releaseHandle(void *handle)
 +{
 +    if (!handle)
 +        return;
 +
 +    if (!QV8Engine_activeHandles.hasLocalData()) 
 +        QV8Engine_activeHandles.setLocalData(new QSet<void *>);
 +
 +    if (QV8Engine_activeHandles.localData()->contains(handle)) {
 +        QV8Engine_activeHandles.localData()->remove(handle);
 +    } else {
 +        qFatal("Handle %p already dead", handle);
 +    }
 +}
 +#endif
 +
 +struct QV8EngineRegistrationData
 +{
 +    QV8EngineRegistrationData() : extensionCount(0) {}
 +
 +    QMutex mutex;
 +    int extensionCount;
 +};
 +Q_GLOBAL_STATIC(QV8EngineRegistrationData, registrationData);
 +
 +QMutex *QV8Engine::registrationMutex()
 +{
 +    return &registrationData()->mutex;
 +}
 +
 +int QV8Engine::registerExtension()
 +{
 +    return registrationData()->extensionCount++;
 +}
 +
 +void QV8Engine::setExtensionData(int index, Deletable *data)
 +{
 +    if (m_extensionData.count() <= index) 
 +        m_extensionData.resize(index + 1);
 +
 +    if (m_extensionData.at(index)) 
 +        delete m_extensionData.at(index);
 +
 +    m_extensionData[index] = data;
 +}
 +
 +double QV8Engine::qtDateTimeToJsDate(const QDateTime &dt)
 +{
 +    // from QScriptEngine::DateTimeToMs()
 +    if (!dt.isValid()) {
 +        return qSNaN();
 +    }
 +    QDateTime utc = dt.toUTC();
 +    QDate date = utc.date();
 +    QTime time = utc.time();
 +    QV8DateConverter::JSC::GregorianDateTime tm;
 +    tm.year = date.year() - 1900;
 +    tm.month = date.month() - 1;
 +    tm.monthDay = date.day();
 +    tm.weekDay = date.dayOfWeek();
 +    tm.yearDay = date.dayOfYear();
 +    tm.hour = time.hour();
 +    tm.minute = time.minute();
 +    tm.second = time.second();
 +    return QV8DateConverter::JSC::gregorianDateTimeToMS(tm, time.msec());
 +}
 +
 +v8::Persistent<v8::Object> *QV8Engine::findOwnerAndStrength(QObject *object, bool *shouldBeStrong)
 +{
 +    QObject *parent = object->parent();
 +    if (!parent) {
 +        // if the object has JS ownership, the object's v8object owns the lifetime of the persistent value.
 +        if (QQmlEngine::objectOwnership(object) == QQmlEngine::JavaScriptOwnership) {
 +            *shouldBeStrong = false;
 +            return &(QQmlData::get(object)->v8object);
 +        }
 +
 +        // no parent, and has CPP ownership - doesn't have an implicit parent.
 +        *shouldBeStrong = true;
 +        return 0;
 +    }
 +
 +    // if it is owned by CPP, it's root parent may still be owned by JS.
 +    // in that case, the owner of the persistent handle is the root parent's v8object.
 +    while (parent->parent())
 +        parent = parent->parent();
 +
 +    if (QQmlEngine::objectOwnership(parent) == QQmlEngine::JavaScriptOwnership) {
 +        // root parent is owned by JS.  It's v8object owns the persistent value in question.
 +        *shouldBeStrong = false;
 +        return &(QQmlData::get(parent)->v8object);
 +    } else {
 +        // root parent has CPP ownership.  The persistent value should not be made weak.
 +        *shouldBeStrong = true;
 +        return 0;
 +    }
 +}
 +
 +QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate)
 +{
 +    // from QScriptEngine::MsToDateTime()
 +    if (qIsNaN(jsDate))
 +        return QDateTime();
 +    QV8DateConverter::JSC::GregorianDateTime tm;
 +    QV8DateConverter::JSC::msToGregorianDateTime(jsDate, tm);
 +
 +    // from QScriptEngine::MsFromTime()
 +    int ms = int(::fmod(jsDate, 1000.0));
 +    if (ms < 0)
 +        ms += int(1000.0);
 +
 +    QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay),
 +                                       QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC);
 +    return convertedUTC.toLocalTime();
 +}
 +
 +void QV8Engine::addRelationshipForGC(QObject *object, v8::Persistent<v8::Value> handle)
 +{
 +    if (handle.IsEmpty())
 +        return;
 +
 +    bool handleShouldBeStrong = false;
 +    v8::Persistent<v8::Object> *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong);
 +    if (handleShouldBeStrong) {
 +        v8::V8::AddImplicitReferences(m_strongReferencer, &handle, 1);
 +    } else if (!implicitOwner->IsEmpty()) {
 +        v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1);
 +    }
 +}
 +
 +void QV8Engine::addRelationshipForGC(QObject *object, QObject *other)
 +{
 +    bool handleShouldBeStrong = false;
 +    v8::Persistent<v8::Object> *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong);
 +    v8::Persistent<v8::Value> handle = QQmlData::get(other, true)->v8object;
 +    if (handleShouldBeStrong) {
 +        v8::V8::AddImplicitReferences(m_strongReferencer, &handle, 1);
 +    } else if (!implicitOwner->IsEmpty()) {
 +        v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1);
 +    }
 +}
 +
 +static QThreadStorage<QV8Engine::ThreadData*> perThreadEngineData;
 +
 +bool QV8Engine::hasThreadData()
 +{
 +    return perThreadEngineData.hasLocalData();
 +}
 +
 +QV8Engine::ThreadData *QV8Engine::threadData()
 +{
 +    Q_ASSERT(perThreadEngineData.hasLocalData());
 +    return perThreadEngineData.localData();
 +}
 +
 +void QV8Engine::ensurePerThreadIsolate()
 +{
 +    if (!perThreadEngineData.hasLocalData())
 +        perThreadEngineData.setLocalData(new ThreadData);
 +}
 +
-     initDeclarativeGlobalObject();
++void QV8Engine::initQmlGlobalObject()
 +{
 +    v8::HandleScope handels;
 +    v8::Context::Scope contextScope(m_context);
 +    initializeGlobal(m_context->Global());
 +    freezeObject(m_context->Global());
 +}
 +
 +void QV8Engine::setEngine(QQmlEngine *engine)
 +{
 +    m_engine = engine;
++    initQmlGlobalObject();
 +}
 +
 +void QV8Engine::setException(v8::Handle<v8::Value> value, v8::Handle<v8::Message> msg)
 +{
 +    m_exception.set(value, msg);
 +}
 +
 +v8::Handle<v8::Value> QV8Engine::throwException(v8::Handle<v8::Value> value)
 +{
 +    setException(value);
 +    v8::ThrowException(value);
 +    return value;
 +}
 +
 +void QV8Engine::clearExceptions()
 +{
 +    m_exception.clear();
 +}
 +
 +v8::Handle<v8::Value> QV8Engine::uncaughtException() const
 +{
 +    if (!hasUncaughtException())
 +        return v8::Handle<v8::Value>();
 +    return m_exception;
 +}
 +
 +bool QV8Engine::hasUncaughtException() const
 +{
 +    return m_exception;
 +}
 +
 +int QV8Engine::uncaughtExceptionLineNumber() const
 +{
 +    return m_exception.lineNumber();
 +}
 +
 +QStringList QV8Engine::uncaughtExceptionBacktrace() const
 +{
 +    return m_exception.backtrace();
 +}
 +
 +/*!
 +  \internal
 +  Save the current exception on stack so it can be set again later.
 +  \sa QV8Engine::restoreException
 +*/
 +void QV8Engine::saveException()
 +{
 +    m_exception.push();
 +}
 +
 +/*!
 +  \internal
 +  Load a saved exception from stack. Current exception, if exists will be dropped
 +  \sa QV8Engine::saveException
 +*/
 +void QV8Engine::restoreException()
 +{
 +    m_exception.pop();
 +}
 +
 +QV8Engine::Exception::Exception() {}
 +
 +QV8Engine::Exception::~Exception()
 +{
 +    Q_ASSERT_X(m_stack.isEmpty(), Q_FUNC_INFO, "Some saved exceptions left. Asymetric pop/push found.");
 +    clear();
 +}
 +
 +void QV8Engine::Exception::set(v8::Handle<v8::Value> value, v8::Handle<v8::Message> message)
 +{
 +    Q_ASSERT_X(!value.IsEmpty(), Q_FUNC_INFO, "Throwing an empty value handle is highly suspected");
 +    clear();
 +    m_value = v8::Persistent<v8::Value>::New(value);
 +    m_message = v8::Persistent<v8::Message>::New(message);
 +}
 +
 +void QV8Engine::Exception::clear()
 +{
 +    m_value.Dispose();
 +    m_value.Clear();
 +    m_message.Dispose();
 +    m_message.Clear();
 +}
 +
 +QV8Engine::Exception::operator bool() const
 +{
 +    return !m_value.IsEmpty();
 +}
 +
 +QV8Engine::Exception::operator v8::Handle<v8::Value>() const
 +{
 +    Q_ASSERT(*this);
 +    return m_value;
 +}
 +
 +int QV8Engine::Exception::lineNumber() const
 +{
 +    if (m_message.IsEmpty())
 +        return -1;
 +    return m_message->GetLineNumber();
 +}
 +
 +QStringList QV8Engine::Exception::backtrace() const
 +{
 +    if (m_message.IsEmpty())
 +        return QStringList();
 +
 +    QStringList backtrace;
 +    v8::Handle<v8::StackTrace> trace = m_message->GetStackTrace();
 +    if (trace.IsEmpty())
 +        // FIXME it should not happen (SetCaptureStackTraceForUncaughtExceptions is called).
 +        return QStringList();
 +
 +    for (int i = 0; i < trace->GetFrameCount(); ++i) {
 +        v8::Local<v8::StackFrame> frame = trace->GetFrame(i);
 +        backtrace.append(QJSConverter::toString(frame->GetFunctionName()));
 +        backtrace.append(QJSConverter::toString(frame->GetFunctionName()));
 +        backtrace.append(QString::fromAscii("()@"));
 +        backtrace.append(QJSConverter::toString(frame->GetScriptName()));
 +        backtrace.append(QString::fromAscii(":"));
 +        backtrace.append(QString::number(frame->GetLineNumber()));
 +    }
 +    return backtrace;
 +}
 +
 +void QV8Engine::Exception::push()
 +{
 +    m_stack.push(qMakePair(m_value, m_message));
 +    m_value.Clear();
 +    m_message.Clear();
 +}
 +
 +void QV8Engine::Exception::pop()
 +{
 +    Q_ASSERT_X(!m_stack.empty(), Q_FUNC_INFO, "Attempt to load unsaved exception found");
 +    ValueMessagePair pair = m_stack.pop();
 +    clear();
 +    m_value = pair.first;
 +    m_message = pair.second;
 +}
 +
 +
 +// Converts a QVariantList to JS.
 +// The result is a new Array object with length equal to the length
 +// of the QVariantList, and the elements being the QVariantList's
 +// elements converted to JS, recursively.
 +v8::Local<v8::Array> QV8Engine::variantListToJS(const QVariantList &lst)
 +{
 +    v8::Local<v8::Array> result = v8::Array::New(lst.size());
 +    for (int i = 0; i < lst.size(); ++i)
 +        result->Set(i, variantToJS(lst.at(i)));
 +    return result;
 +}
 +
 +// Converts a JS Array object to a QVariantList.
 +// The result is a QVariantList with length equal to the length
 +// of the JS Array, and elements being the JS Array's elements
 +// converted to QVariants, recursively.
 +QVariantList QV8Engine::variantListFromJS(v8::Handle<v8::Array> jsArray)
 +{
 +    QVariantList result;
 +    int hash = jsArray->GetIdentityHash();
 +    if (visitedConversionObjects.contains(hash))
 +        return result; // Avoid recursion.
 +    v8::HandleScope handleScope;
 +    visitedConversionObjects.insert(hash);
 +    uint32_t length = jsArray->Length();
 +    for (uint32_t i = 0; i < length; ++i)
 +        result.append(variantFromJS(jsArray->Get(i)));
 +    visitedConversionObjects.remove(hash);
 +    return result;
 +}
 +
 +// Converts a QVariantMap to JS.
 +// The result is a new Object object with property names being
 +// the keys of the QVariantMap, and values being the values of
 +// the QVariantMap converted to JS, recursively.
 +v8::Local<v8::Object> QV8Engine::variantMapToJS(const QVariantMap &vmap)
 +{
 +    v8::Local<v8::Object> result = v8::Object::New();
 +    QVariantMap::const_iterator it;
 +    for (it = vmap.constBegin(); it != vmap.constEnd(); ++it)
 +        result->Set(QJSConverter::toString(it.key()), variantToJS(it.value()));
 +    return result;
 +}
 +
 +// Converts a JS Object to a QVariantMap.
 +// The result is a QVariantMap with keys being the property names
 +// of the object, and values being the values of the JS object's
 +// properties converted to QVariants, recursively.
 +QVariantMap QV8Engine::variantMapFromJS(v8::Handle<v8::Object> jsObject)
 +{
 +    QVariantMap result;
 +
 +    v8::HandleScope handleScope;
 +    v8::Handle<v8::Array> propertyNames = jsObject->GetPropertyNames();
 +    uint32_t length = propertyNames->Length();
 +    if (length == 0)
 +        return result;
 +
 +    int hash = jsObject->GetIdentityHash();
 +    if (visitedConversionObjects.contains(hash))
 +        return result; // Avoid recursion.
 +
 +    visitedConversionObjects.insert(hash);
 +    // TODO: Only object's own property names. Include non-enumerable properties.
 +    for (uint32_t i = 0; i < length; ++i) {
 +        v8::Handle<v8::Value> name = propertyNames->Get(i);
 +        result.insert(QJSConverter::toString(name->ToString()), variantFromJS(jsObject->Get(name)));
 +    }
 +    visitedConversionObjects.remove(hash);
 +    return result;
 +}
 +
 +// Converts the meta-type defined by the given type and data to JS.
 +// Returns the value if conversion succeeded, an empty handle otherwise.
 +v8::Handle<v8::Value> QV8Engine::metaTypeToJS(int type, const void *data)
 +{
 +    Q_ASSERT(data != 0);
 +    v8::Handle<v8::Value> result;
 +
 +    // check if it's one of the types we know
 +    switch (QMetaType::Type(type)) {
 +    case QMetaType::Void:
 +        return v8::Undefined();
 +    case QMetaType::Bool:
 +        return v8::Boolean::New(*reinterpret_cast<const bool*>(data));
 +    case QMetaType::Int:
 +        return v8::Int32::New(*reinterpret_cast<const int*>(data));
 +    case QMetaType::UInt:
 +        return v8::Uint32::New(*reinterpret_cast<const uint*>(data));
 +    case QMetaType::LongLong:
 +        return v8::Number::New(double(*reinterpret_cast<const qlonglong*>(data)));
 +    case QMetaType::ULongLong:
 +#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
 +#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
 +        return v8::Number::New(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
 +#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
 +        return v8::Number::New(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
 +#else
 +        return v8::Number::New(double(*reinterpret_cast<const qulonglong*>(data)));
 +#endif
 +    case QMetaType::Double:
 +        return v8::Number::New(double(*reinterpret_cast<const double*>(data)));
 +    case QMetaType::QString:
 +        return QJSConverter::toString(*reinterpret_cast<const QString*>(data));
 +    case QMetaType::Float:
 +        return v8::Number::New(*reinterpret_cast<const float*>(data));
 +    case QMetaType::Short:
 +        return v8::Int32::New(*reinterpret_cast<const short*>(data));
 +    case QMetaType::UShort:
 +        return v8::Uint32::New(*reinterpret_cast<const unsigned short*>(data));
 +    case QMetaType::Char:
 +        return v8::Int32::New(*reinterpret_cast<const char*>(data));
 +    case QMetaType::UChar:
 +        return v8::Uint32::New(*reinterpret_cast<const unsigned char*>(data));
 +    case QMetaType::QChar:
 +        return v8::Uint32::New((*reinterpret_cast<const QChar*>(data)).unicode());
 +    case QMetaType::QStringList:
 +        result = QJSConverter::toStringList(*reinterpret_cast<const QStringList *>(data));
 +        break;
 +    case QMetaType::QVariantList:
 +        result = variantListToJS(*reinterpret_cast<const QVariantList *>(data));
 +        break;
 +    case QMetaType::QVariantMap:
 +        result = variantMapToJS(*reinterpret_cast<const QVariantMap *>(data));
 +        break;
 +    case QMetaType::QDateTime:
 +        result = QJSConverter::toDateTime(*reinterpret_cast<const QDateTime *>(data));
 +        break;
 +    case QMetaType::QDate:
 +        result = QJSConverter::toDateTime(QDateTime(*reinterpret_cast<const QDate *>(data)));
 +        break;
 +    case QMetaType::QRegExp:
 +        result = QJSConverter::toRegExp(*reinterpret_cast<const QRegExp *>(data));
 +        break;
 +    case QMetaType::QObjectStar:
 +    case QMetaType::QWidgetStar:
 +        result = newQObject(*reinterpret_cast<QObject* const *>(data));
 +        break;
 +    case QMetaType::QVariant:
 +        result = variantToJS(*reinterpret_cast<const QVariant*>(data));
 +        break;
 +    default:
 +        if (type == qMetaTypeId<QJSValue>()) {
 +            return QJSValuePrivate::get(*reinterpret_cast<const QJSValue*>(data))->asV8Value(this);
 +        } else {
 +            QByteArray typeName = QMetaType::typeName(type);
 +            if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) {
 +                return v8::Null();
 +            } else {
 +                // Fall back to wrapping in a QVariant.
 +                result = newVariant(QVariant(type, data));
 +            }
 +        }
 +    }
 +    return result;
 +}
 +
 +// Converts a JS value to a meta-type.
 +// data must point to a place that can store a value of the given type.
 +// Returns true if conversion succeeded, false otherwise.
 +bool QV8Engine::metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data) {
 +    // check if it's one of the types we know
 +    switch (QMetaType::Type(type)) {
 +    case QMetaType::Bool:
 +        *reinterpret_cast<bool*>(data) = value->ToBoolean()->Value();
 +        return true;
 +    case QMetaType::Int:
 +        *reinterpret_cast<int*>(data) = value->ToInt32()->Value();
 +        return true;
 +    case QMetaType::UInt:
 +        *reinterpret_cast<uint*>(data) = value->ToUint32()->Value();
 +        return true;
 +    case QMetaType::LongLong:
 +        *reinterpret_cast<qlonglong*>(data) = qlonglong(value->ToInteger()->Value());
 +        return true;
 +    case QMetaType::ULongLong:
 +        *reinterpret_cast<qulonglong*>(data) = qulonglong(value->ToInteger()->Value());
 +        return true;
 +    case QMetaType::Double:
 +        *reinterpret_cast<double*>(data) = value->ToNumber()->Value();
 +        return true;
 +    case QMetaType::QString:
 +        if (value->IsUndefined() || value->IsNull())
 +            *reinterpret_cast<QString*>(data) = QString();
 +        else
 +            *reinterpret_cast<QString*>(data) = QJSConverter::toString(value->ToString());
 +        return true;
 +    case QMetaType::Float:
 +        *reinterpret_cast<float*>(data) = value->ToNumber()->Value();
 +        return true;
 +    case QMetaType::Short:
 +        *reinterpret_cast<short*>(data) = short(value->ToInt32()->Value());
 +        return true;
 +    case QMetaType::UShort:
 +        *reinterpret_cast<unsigned short*>(data) = ushort(value->ToInt32()->Value()); // ### QScript::ToUInt16()
 +        return true;
 +    case QMetaType::Char:
 +        *reinterpret_cast<char*>(data) = char(value->ToInt32()->Value());
 +        return true;
 +    case QMetaType::UChar:
 +        *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->ToInt32()->Value());
 +        return true;
 +    case QMetaType::QChar:
 +        if (value->IsString()) {
 +            QString str = QJSConverter::toString(v8::Handle<v8::String>::Cast(value));
 +            *reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
 +        } else {
 +            *reinterpret_cast<QChar*>(data) = QChar(ushort(value->ToInt32()->Value())); // ### QScript::ToUInt16()
 +        }
 +        return true;
 +    case QMetaType::QDateTime:
 +        if (value->IsDate()) {
 +            *reinterpret_cast<QDateTime *>(data) = QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(value));
 +            return true;
 +        } break;
 +    case QMetaType::QDate:
 +        if (value->IsDate()) {
 +            *reinterpret_cast<QDate *>(data) = QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(value)).date();
 +            return true;
 +        } break;
 +    case QMetaType::QRegExp:
 +        if (value->IsRegExp()) {
 +            *reinterpret_cast<QRegExp *>(data) = QJSConverter::toRegExp(v8::Handle<v8::RegExp>::Cast(value));
 +            return true;
 +        } break;
 +    case QMetaType::QObjectStar:
 +        if (isQObject(value) || value->IsNull()) {
 +            *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(value);
 +            return true;
 +        } break;
 +    case QMetaType::QWidgetStar:
 +        if (isQObject(value) || value->IsNull()) {
 +            QObject *qo = qtObjectFromJS(value);
 +            if (!qo || qo->isWidgetType()) {
 +                *reinterpret_cast<QWidget* *>(data) = reinterpret_cast<QWidget*>(qo);
 +                return true;
 +            }
 +        } break;
 +    case QMetaType::QStringList:
 +        if (value->IsArray()) {
 +            *reinterpret_cast<QStringList *>(data) = QJSConverter::toStringList(v8::Handle<v8::Array>::Cast(value));
 +            return true;
 +        } break;
 +    case QMetaType::QVariantList:
 +        if (value->IsArray()) {
 +            *reinterpret_cast<QVariantList *>(data) = variantListFromJS(v8::Handle<v8::Array>::Cast(value));
 +            return true;
 +        } break;
 +    case QMetaType::QVariantMap:
 +        if (value->IsObject()) {
 +            *reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(v8::Handle<v8::Object>::Cast(value));
 +            return true;
 +        } break;
 +    case QMetaType::QVariant:
 +        *reinterpret_cast<QVariant*>(data) = variantFromJS(value);
 +        return true;
 +    default:
 +    ;
 +    }
 +
 +#if 0
 +    if (isQtVariant(value)) {
 +        const QVariant &var = variantValue(value);
 +        // ### Enable once constructInPlace() is in qt master.
 +        if (var.userType() == type) {
 +            QMetaType::constructInPlace(type, data, var.constData());
 +            return true;
 +        }
 +        if (var.canConvert(QVariant::Type(type))) {
 +            QVariant vv = var;
 +            vv.convert(QVariant::Type(type));
 +            Q_ASSERT(vv.userType() == type);
 +            QMetaType::constructInPlace(type, data, vv.constData());
 +            return true;
 +        }
 +
 +    }
 +#endif
 +
 +    // Try to use magic; for compatibility with qscriptvalue_cast.
 +
 +    QByteArray name = QMetaType::typeName(type);
 +    if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(data)))
 +        return true;
 +    if (isVariant(value) && name.endsWith('*')) {
 +        int valueType = QMetaType::type(name.left(name.size()-1));
 +        QVariant &var = variantValue(value);
 +        if (valueType == var.userType()) {
 +            // We have T t, T* is requested, so return &t.
 +            *reinterpret_cast<void* *>(data) = var.data();
 +            return true;
 +        } else {
 +            // Look in the prototype chain.
 +            v8::Handle<v8::Value> proto = value->ToObject()->GetPrototype();
 +            while (proto->IsObject()) {
 +                bool canCast = false;
 +                if (isVariant(proto)) {
 +                    canCast = (type == variantValue(proto).userType())
 +                              || (valueType && (valueType == variantValue(proto).userType()));
 +                }
 +                else if (isQObject(proto)) {
 +                    QByteArray className = name.left(name.size()-1);
 +                    if (QObject *qobject = qtObjectFromJS(proto))
 +                        canCast = qobject->qt_metacast(className) != 0;
 +                }
 +                if (canCast) {
 +                    QByteArray varTypeName = QMetaType::typeName(var.userType());
 +                    if (varTypeName.endsWith('*'))
 +                        *reinterpret_cast<void* *>(data) = *reinterpret_cast<void* *>(var.data());
 +                    else
 +                        *reinterpret_cast<void* *>(data) = var.data();
 +                    return true;
 +                }
 +                proto = proto->ToObject()->GetPrototype();
 +            }
 +        }
 +    } else if (value->IsNull() && name.endsWith('*')) {
 +        *reinterpret_cast<void* *>(data) = 0;
 +        return true;
 +    } else if (type == qMetaTypeId<QJSValue>()) {
 +        *reinterpret_cast<QJSValue*>(data) = QJSValuePrivate::get(new QJSValuePrivate(this, value));
 +        return true;
 +    }
 +
 +    return false;
 +}
 +
 +// Converts a QVariant to JS.
 +v8::Handle<v8::Value> QV8Engine::variantToJS(const QVariant &value)
 +{
 +    return metaTypeToJS(value.userType(), value.constData());
 +}
 +
 +// Converts a JS value to a QVariant.
 +// Null, Undefined -> QVariant() (invalid)
 +// Boolean -> QVariant(bool)
 +// Number -> QVariant(double)
 +// String -> QVariant(QString)
 +// Array -> QVariantList(...)
 +// Date -> QVariant(QDateTime)
 +// RegExp -> QVariant(QRegExp)
 +// [Any other object] -> QVariantMap(...)
 +QVariant QV8Engine::variantFromJS(v8::Handle<v8::Value> value)
 +{
 +    Q_ASSERT(!value.IsEmpty());
 +    if (value->IsNull() || value->IsUndefined())
 +        return QVariant();
 +    if (value->IsBoolean())
 +        return value->ToBoolean()->Value();
 +    if (value->IsInt32())
 +        return value->ToInt32()->Value();
 +    if (value->IsNumber())
 +        return value->ToNumber()->Value();
 +    if (value->IsString())
 +        return QJSConverter::toString(value->ToString());
 +    Q_ASSERT(value->IsObject());
 +    if (value->IsArray())
 +        return variantListFromJS(v8::Handle<v8::Array>::Cast(value));
 +    if (value->IsDate())
 +        return QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(value));
 +    if (value->IsRegExp())
 +        return QJSConverter::toRegExp(v8::Handle<v8::RegExp>::Cast(value));
 +    if (isVariant(value))
 +        return variantValue(value);
 +    if (isQObject(value))
 +        return qVariantFromValue(qtObjectFromJS(value));
 +    return variantMapFromJS(value->ToObject());
 +}
 +
 +bool QV8Engine::convertToNativeQObject(v8::Handle<v8::Value> value,
 +                                                  const QByteArray &targetType,
 +                                                  void **result)
 +{
 +    if (!targetType.endsWith('*'))
 +        return false;
 +    if (QObject *qobject = qtObjectFromJS(value)) {
 +        int start = targetType.startsWith("const ") ? 6 : 0;
 +        QByteArray className = targetType.mid(start, targetType.size()-start-1);
 +        if (void *instance = qobject->qt_metacast(className)) {
 +            *result = instance;
 +            return true;
 +        }
 +    }
 +    return false;
 +}
 +
 +QObject *QV8Engine::qtObjectFromJS(v8::Handle<v8::Value> value)
 +{
 +    if (!value->IsObject())
 +        return 0;
 +
 +    QV8ObjectResource *r = (QV8ObjectResource *)value->ToObject()->GetExternalResource();
 +    if (!r)
 +        return 0;
 +    QV8ObjectResource::ResourceType type = r->resourceType();
 +    if (type == QV8ObjectResource::QObjectType)
 +        return qobjectWrapper()->toQObject(r);
 +    else if (type == QV8ObjectResource::VariantType) {
 +        QVariant variant = variantWrapper()->toVariant(r);
 +        int type = variant.userType();
 +        if ((type == QMetaType::QObjectStar) || (type == QMetaType::QWidgetStar))
 +            return *reinterpret_cast<QObject* const *>(variant.constData());
 +    }
 +    return 0;
 +}
 +
 +
 +QVariant &QV8Engine::variantValue(v8::Handle<v8::Value> value)
 +{
 +    return variantWrapper()->variantValue(value);
 +}
 +
 +// Creates a QVariant wrapper object.
 +v8::Local<v8::Object> QV8Engine::newVariant(const QVariant &value)
 +{
 +    return variantWrapper()->newVariant(value);
 +}
 +
 +QScriptPassPointer<QJSValuePrivate> QV8Engine::evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch)
 +{
 +    v8::HandleScope handleScope;
 +
 +    clearExceptions();
 +    if (script.IsEmpty()) {
 +        v8::Handle<v8::Value> exception = tryCatch.Exception();
 +        if (exception.IsEmpty()) {
 +            // This is possible on syntax errors like { a:12, b:21 } <- missing "(", ")" around expression.
 +            return new QJSValuePrivate(this);
 +        }
 +        setException(exception, tryCatch.Message());
 +        return new QJSValuePrivate(this, exception);
 +    }
 +    v8::Handle<v8::Value> result;
 +    result = script->Run();
 +    if (result.IsEmpty()) {
 +        v8::Handle<v8::Value> exception = tryCatch.Exception();
 +        // TODO: figure out why v8 doesn't always produce an exception value
 +        //Q_ASSERT(!exception.IsEmpty());
 +        if (exception.IsEmpty())
 +            exception = v8::Exception::Error(v8::String::New("missing exception value"));
 +        setException(exception, tryCatch.Message());
 +        return new QJSValuePrivate(this, exception);
 +    }
 +    return new QJSValuePrivate(this, result);
 +}
 +
 +QJSValue QV8Engine::scriptValueFromInternal(v8::Handle<v8::Value> value) const
 +{
 +    if (value.IsEmpty())
 +        return QJSValuePrivate::get(new QJSValuePrivate(const_cast<QV8Engine*>(this)));
 +    return QJSValuePrivate::get(new QJSValuePrivate(const_cast<QV8Engine*>(this), value));
 +}
 +
 +QScriptPassPointer<QJSValuePrivate> QV8Engine::newArray(uint length)
 +{
 +    return new QJSValuePrivate(this, v8::Array::New(length));
 +}
 +
 +void QV8Engine::emitSignalHandlerException()
 +{
 +    emit q->signalHandlerException(scriptValueFromInternal(uncaughtException()));
 +}
 +
 +void QV8Engine::startTimer(const QString &timerName)
 +{
 +    if (!m_time.isValid())
 +        m_time.start();
 +    m_startedTimers[timerName] = m_time.elapsed();
 +}
 +
 +qint64 QV8Engine::stopTimer(const QString &timerName, bool *wasRunning)
 +{
 +    if (!m_startedTimers.contains(timerName)) {
 +        *wasRunning = false;
 +        return 0;
 +    }
 +    *wasRunning = true;
 +    qint64 startedAt = m_startedTimers.take(timerName);
 +    return m_time.elapsed() - startedAt;
 +}
 +
 +int QV8Engine::consoleCountHelper(const QString &file, int line, int column)
 +{
 +    const QString key = file + QString::number(line) + QString::number(column);
 +    int number = m_consoleCount.value(key, 0);
 +    number++;
 +    m_consoleCount.insert(key, number);
 +    return number;
 +}
 +
 +void QV8GCCallback::registerGcPrologueCallback()
 +{
 +    QV8Engine::ThreadData *td = QV8Engine::threadData();
 +    if (!td->gcPrologueCallbackRegistered) {
 +        td->gcPrologueCallbackRegistered = true;
 +        v8::V8::AddGCPrologueCallback(QV8GCCallback::garbageCollectorPrologueCallback, v8::kGCTypeMarkSweepCompact);
 +    }
 +}
 +
 +QV8GCCallback::Node::Node(PrologueCallback callback)
 +    : prologueCallback(callback)
 +{
 +}
 +
 +QV8GCCallback::Node::~Node()
 +{
 +    node.remove();
 +}
 +
 +/*
 +   Ensure that each persistent handle is strong if it has CPP ownership
 +   and has no implicitly JS owned object owner in its parent chain, and
 +   weak otherwise.
 +
 +   Any weak handle whose parent object is still alive will have an implicit
 +   reference (between the parent and the handle) added, so that it will
 +   not be collected.
 +
 +   Note that this callback is registered only for kGCTypeMarkSweepCompact
 +   collection cycles, as it is during collection cycles of that type
 +   in which weak persistent handle callbacks are called when required.
 + */
 +void QV8GCCallback::garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackFlags)
 +{
 +    if (!QV8Engine::hasThreadData())
 +        return;
 +
 +    QV8Engine::ThreadData *td = QV8Engine::threadData();
 +    QV8GCCallback::Node *currNode = td->gcCallbackNodes.first();
 +
 +    while (currNode) {
 +        // The client which adds itself to the list is responsible
 +        // for maintaining the correct implicit references in the
 +        // specified callback.
 +        currNode->prologueCallback(currNode);
 +        currNode = td->gcCallbackNodes.next(currNode);
 +    }
 +}
 +
 +void QV8GCCallback::addGcCallbackNode(QV8GCCallback::Node *node)
 +{
 +    QV8Engine::ThreadData *td = QV8Engine::threadData();
 +    td->gcCallbackNodes.insert(node);
 +}
 +
 +QV8Engine::ThreadData::ThreadData()
 +    : gcPrologueCallbackRegistered(false)
 +{
 +    if (!v8::Isolate::GetCurrent()) {
 +        isolate = v8::Isolate::New();
 +        isolate->Enter();
 +    } else {
 +        isolate = 0;
 +    }
 +}
 +
 +QV8Engine::ThreadData::~ThreadData()
 +{
 +    if (isolate) {
 +        isolate->Exit();
 +        isolate->Dispose();
 +        isolate = 0;
 +    }
 +}
 +
 +QT_END_NAMESPACE
 +
index ebb21f8,0000000..7173ae4
mode 100644,000000..100644
--- /dev/null
@@@ -1,155 -1,0 +1,173 @@@
- ** $QT_BEGIN_LICENSE:LGPL-ONLY$
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
- ** This file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure 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 have questions regarding the use of this file, please contact
- ** us via http://www.qt-project.org/.
++** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QV8ENGINE_IMPL_P_H
 +#define QV8ENGINE_IMPL_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 "qv8engine_p.h"
 +#include "qjsvalue_p.h"
 +#include "qjsconverter_p.h"
 +#include "qjsvalueiterator_p.h"
 +
 +QT_BEGIN_NAMESPACE
 +
 +inline v8::Handle<v8::Value> QV8Engine::makeJSValue(bool value)
 +{
 +    return value ? v8::True() : v8::False();
 +}
 +
 +inline v8::Local<v8::Value> QV8Engine::makeJSValue(int value)
 +{
 +    return v8::Integer::New(value);
 +}
 +
 +inline v8::Local<v8::Value> QV8Engine::makeJSValue(uint value)
 +{
 +    return v8::Integer::NewFromUnsigned(value);
 +}
 +
 +inline v8::Local<v8::Value> QV8Engine::makeJSValue(double value)
 +{
 +    return v8::Number::New(value);
 +}
 +
 +inline v8::Handle<v8::Value> QV8Engine::makeJSValue(QJSValue::SpecialValue value) {
 +    if (value == QJSValue::NullValue)
 +        return v8::Null();
 +    return v8::Undefined();
 +}
 +
 +inline v8::Local<v8::Value> QV8Engine::makeJSValue(const QString &value)
 +{
 +    return QJSConverter::toString(value);
 +}
 +
 +class QtScriptBagCleaner
 +{
 +public:
 +    template<class T>
 +    void operator () (T* value) const
 +    {
 +        value->reinitialize();
 +    }
 +    void operator () (QJSValueIteratorPrivate *iterator) const
 +    {
 +        iterator->invalidate();
 +    }
 +};
 +
 +inline void QV8Engine::registerValue(QJSValuePrivate *data)
 +{
 +    m_values.insert(data);
 +}
 +
 +inline void QV8Engine::unregisterValue(QJSValuePrivate *data)
 +{
 +    m_values.remove(data);
 +}
 +
 +inline void QV8Engine::invalidateAllValues()
 +{
 +    ValueList::iterator it;
 +    for (it = m_values.begin(); it != m_values.end(); it = it.erase())
 +        (*it)->invalidate();
 +    Q_ASSERT(m_values.isEmpty());
 +}
 +
 +inline void QV8Engine::registerValueIterator(QJSValueIteratorPrivate *data)
 +{
 +    m_valueIterators.insert(data);
 +}
 +
 +inline void QV8Engine::unregisterValueIterator(QJSValueIteratorPrivate *data)
 +{
 +    m_valueIterators.remove(data);
 +}
 +
 +inline void QV8Engine::invalidateAllIterators()
 +{
 +    ValueIteratorList::iterator it;
 +    for (it = m_valueIterators.begin(); it != m_valueIterators.end(); it = it.erase())
 +        (*it)->invalidate();
 +    Q_ASSERT(m_valueIterators.isEmpty());
 +}
 +
 +/*!
 +  \internal
 +  \note property can be index (v8::Integer) or a property (v8::String) name, according to ECMA script
 +  property would be converted to a string.
 +*/
 +inline QJSValuePrivate::PropertyFlags QV8Engine::getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property)
 +{
 +    QJSValuePrivate::PropertyFlags flags = m_originalGlobalObject.getPropertyFlags(object, property);
 +    return flags;
 +}
 +
 +QScriptPassPointer<QJSValuePrivate> QV8Engine::evaluate(const QString& program, const QString& fileName, int lineNumber)
 +{
 +    v8::TryCatch tryCatch;
 +    v8::ScriptOrigin scriptOrigin(QJSConverter::toString(fileName), v8::Integer::New(lineNumber - 1));
 +    v8::Handle<v8::Script> script;
 +    script = v8::Script::Compile(QJSConverter::toString(program), &scriptOrigin);
 +    if (script.IsEmpty()) {
 +        // TODO: Why don't we get the exception, as with Script::Compile()?
 +        // Q_ASSERT(tryCatch.HasCaught());
 +        v8::Handle<v8::Value> error = v8::Exception::SyntaxError(v8::String::New(""));
 +        setException(error);
 +        return new QJSValuePrivate(this, error);
 +    }
 +    return evaluate(script, tryCatch);
 +}
 +
 +QT_END_NAMESPACE
 +
 +#endif // QV8ENGINE_IMPL_P_H
index 22a8d75,0000000..bc57b27
mode 100644,000000..100644
--- /dev/null
@@@ -1,631 -1,0 +1,631 @@@
-     void initDeclarativeGlobalObject();
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQMLV8ENGINE_P_H
 +#define QQMLV8ENGINE_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/qvariant.h>
 +#include <QtCore/qset.h>
 +#include <QtCore/qmutex.h>
 +#include <QtCore/qstack.h>
 +#include <QtCore/qstringlist.h>
 +#include <QtCore/QElapsedTimer>
 +#include <QtCore/QThreadStorage>
 +
 +#include <private/qv8_p.h>
 +#include <qjsengine.h>
 +#include <qjsvalue.h>
 +#include "qjsvalue_p.h"
 +#include "qjsvalueiterator_p.h"
 +#include "qscriptoriginalglobalobject_p.h"
 +#include "qscripttools_p.h"
 +
 +#include <private/qqmlpropertycache_p.h>
 +
 +#include "qv8contextwrapper_p.h"
 +#include "qv8qobjectwrapper_p.h"
 +#include "qv8stringwrapper_p.h"
 +#include "qv8typewrapper_p.h"
 +#include "qv8listwrapper_p.h"
 +#include "qv8variantwrapper_p.h"
 +#include "qv8valuetypewrapper_p.h"
 +#include "qv8sequencewrapper_p.h"
 +
 +QT_BEGIN_NAMESPACE
 +
 +
 +// Uncomment the following line to enable global handle debugging.  When enabled, all the persistent
 +// handles allocated using qPersistentNew() (or registered with qPersistentRegsiter()) and disposed
 +// with qPersistentDispose() are tracked.  If you try and do something illegal, like double disposing
 +// a handle, qFatal() is called.
 +// #define QML_GLOBAL_HANDLE_DEBUGGING
 +
 +#define V8_RESOURCE_TYPE(resourcetype) \
 +public: \
 +    enum { V8ResourceType = QV8ObjectResource:: resourcetype }; \
 +    virtual QV8ObjectResource::ResourceType resourceType() const { return QV8ObjectResource:: resourcetype; } \
 +private: 
 +
 +#define V8ENGINE() ((QV8Engine *)v8::External::Unwrap(args.Data()))
 +#define V8FUNCTION(function, engine) v8::FunctionTemplate::New(function, v8::External::Wrap((QV8Engine*)engine))->GetFunction()
 +#define V8THROW_ERROR(string) { \
 +    v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
 +    return v8::Handle<v8::Value>(); \
 +}
 +#define V8THROW_TYPE(string) { \
 +    v8::ThrowException(v8::Exception::TypeError(v8::String::New(string))); \
 +    return v8::Handle<v8::Value>(); \
 +}
 +#define V8ENGINE_ACCESSOR() ((QV8Engine *)v8::External::Unwrap(info.Data()));
 +#define V8THROW_ERROR_SETTER(string) { \
 +    v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
 +    return; \
 +}
 +
 +#define V8_DEFINE_EXTENSION(dataclass, datafunction) \
 +    static inline dataclass *datafunction(QV8Engine *engine) \
 +    { \
 +        static int extensionId = -1; \
 +        if (extensionId == -1) { \
 +            QV8Engine::registrationMutex()->lock(); \
 +            if (extensionId == -1) \
 +                extensionId = QV8Engine::registerExtension(); \
 +            QV8Engine::registrationMutex()->unlock(); \
 +        } \
 +        dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
 +        if (!rv) { \
 +            rv = new dataclass(engine); \
 +            engine->setExtensionData(extensionId, rv); \
 +        } \
 +        return rv; \
 +    } \
 +
 +
 +class QV8Engine;
 +class QV8ObjectResource : public v8::Object::ExternalResource
 +{
 +public:
 +    QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
 +    enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType, 
 +                        ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType,
 +                        ListModelType, Context2DType, Context2DStyleType, Context2DPixelArrayType, 
 +                        ParticleDataType, SignalHandlerType, IncubatorType, VisualDataItemType,
 +                        SequenceType, LocaleDataType };
 +    virtual ResourceType resourceType() const = 0;
 +
 +    QV8Engine *engine;
 +};
 +
 +template<class T>
 +inline T *v8_resource_cast(v8::Handle<v8::Object> object) {
 +    QV8ObjectResource *resource = static_cast<QV8ObjectResource *>(object->GetExternalResource());
 +    return (resource && (quint32)resource->resourceType() == (quint32)T::V8ResourceType)?static_cast<T *>(resource):0;
 +}
 +
 +template<class T>
 +inline T *v8_resource_check(v8::Handle<v8::Object> object) {
 +    T *resource = static_cast<T *>(object->GetExternalResource());
 +    Q_ASSERT(resource && resource->resourceType() == (quint32)T::V8ResourceType);
 +    return resource;
 +}
 +
 +// Used to allow a QObject method take and return raw V8 handles without having to expose
 +// v8 in the public API.
 +// Use like this:
 +//     class MyClass : public QObject {
 +//         Q_OBJECT
 +//         ...
 +//         Q_INVOKABLE void myMethod(QQmlV8Function*);
 +//     };
 +// The QQmlV8Function - and consequently the arguments and return value - only remains 
 +// valid during the call.  If the return value isn't set within myMethod(), the will return
 +// undefined.
 +class QV8Engine;
 +class QQmlV8Function
 +{
 +public:
 +    int Length() const { return _ac; }
 +    v8::Local<v8::Value> operator[](int idx) { return (*_a)->Get(idx); }
 +    QQmlContextData *context() { return _c; }
 +    v8::Handle<v8::Object> qmlGlobal() { return *_g; }
 +    void returnValue(v8::Handle<v8::Value> rv) { *_r = rv; }
 +    QV8Engine *engine() const { return _e; }
 +private:
 +    friend class QV8QObjectWrapper;
 +    QQmlV8Function();
 +    QQmlV8Function(const QQmlV8Function &);
 +    QQmlV8Function &operator=(const QQmlV8Function &);
 +
 +    QQmlV8Function(int length, v8::Handle<v8::Object> &args, 
 +                           v8::Handle<v8::Value> &rv, v8::Handle<v8::Object> &global,
 +                           QQmlContextData *c, QV8Engine *e)
 +    : _ac(length), _a(&args), _r(&rv), _g(&global), _c(c), _e(e) {}
 +
 +    int _ac;
 +    v8::Handle<v8::Object> *_a;
 +    v8::Handle<v8::Value> *_r;
 +    v8::Handle<v8::Object> *_g;
 +    QQmlContextData *_c;
 +    QV8Engine *_e;
 +};
 +
 +class QQmlV8Handle
 +{
 +public:
 +    QQmlV8Handle() : d(0) {}
 +    QQmlV8Handle(const QQmlV8Handle &other) : d(other.d) {}
 +    QQmlV8Handle &operator=(const QQmlV8Handle &other) { d = other.d; return *this; }
 +
 +    static QQmlV8Handle fromHandle(v8::Handle<v8::Value> h) {
 +        return QQmlV8Handle(*h);
 +    }
 +    v8::Handle<v8::Value> toHandle() const {
 +        return v8::Handle<v8::Value>((v8::Value *)d);
 +    }
 +private:
 +    QQmlV8Handle(void *d) : d(d) {}
 +    void *d;
 +};
 +
 +class QObject;
 +class QQmlEngine;
 +class QQmlValueType;
 +class QNetworkAccessManager;
 +class QQmlContextData;
 +
 +class Q_AUTOTEST_EXPORT QV8GCCallback
 +{
 +private:
 +    class ThreadData;
 +public:
 +    static void garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackFlags);
 +    static void registerGcPrologueCallback();
 +
 +    class Q_AUTOTEST_EXPORT Node {
 +    public:
 +        typedef void (*PrologueCallback)(Node *node);
 +        Node(PrologueCallback callback);
 +        ~Node();
 +
 +        QIntrusiveListNode node;
 +        PrologueCallback prologueCallback;
 +    };
 +
 +    static void addGcCallbackNode(Node *node);
 +};
 +
 +class Q_QML_EXPORT QV8Engine
 +{
 +public:
 +    static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); }
 +    static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
 +
 +    QV8Engine(QJSEngine* qq,QJSEngine::ContextOwnership ownership = QJSEngine::CreateNewContext);
 +    virtual ~QV8Engine();
 +
 +    // This enum should be in sync with QQmlEngine::ObjectOwnership
 +    enum ObjectOwnership { CppOwnership, JavaScriptOwnership };
 +
 +    struct Deletable {
 +        virtual ~Deletable() {}
 +    };
 +
 +    class Exception
 +    {
 +        typedef QPair<v8::Persistent<v8::Value>, v8::Persistent<v8::Message> > ValueMessagePair;
 +
 +        v8::Persistent<v8::Value> m_value;
 +        v8::Persistent<v8::Message> m_message;
 +        QStack<ValueMessagePair> m_stack;
 +
 +        Q_DISABLE_COPY(Exception)
 +    public:
 +        inline Exception();
 +        inline ~Exception();
 +        inline void set(v8::Handle<v8::Value> value, v8::Handle<v8::Message> message);
 +        inline void clear();
 +        inline operator bool() const;
 +        inline operator v8::Handle<v8::Value>() const;
 +        inline int lineNumber() const;
 +        inline QStringList backtrace() const;
 +
 +        inline void push();
 +        inline void pop();
 +    };
 +
++    void initQmlGlobalObject();
 +    void setEngine(QQmlEngine *engine);
 +    QQmlEngine *engine() { return m_engine; }
 +    v8::Local<v8::Object> global() { return m_context->Global(); }
 +    v8::Handle<v8::Context> context() const { return m_context; }
 +
 +    inline void registerValue(QJSValuePrivate *data);
 +    inline void unregisterValue(QJSValuePrivate *data);
 +    inline void invalidateAllValues();
 +
 +    inline void registerValueIterator(QJSValueIteratorPrivate *data);
 +    inline void unregisterValueIterator(QJSValueIteratorPrivate *data);
 +    inline void invalidateAllIterators();
 +
 +    QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; }
 +    QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
 +    QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
 +    QV8ListWrapper *listWrapper() { return &m_listWrapper; }
 +    QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; }
 +    QV8ValueTypeWrapper *valueTypeWrapper() { return &m_valueTypeWrapper; }
 +    QV8SequenceWrapper *sequenceWrapper() { return &m_sequenceWrapper; }
 +
 +    void *xmlHttpRequestData() { return m_xmlHttpRequestData; }
 +
 +    Deletable *listModelData() { return m_listModelData; }
 +    void setListModelData(Deletable *d) { if (m_listModelData) delete m_listModelData; m_listModelData = d; }
 +
 +    QQmlContextData *callingContext();
 +
 +    v8::Local<v8::Array> getOwnPropertyNames(v8::Handle<v8::Object>);
 +    inline QJSValuePrivate::PropertyFlags getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property);
 +    void freezeObject(v8::Handle<v8::Value>);
 +
 +    inline QString toString(v8::Handle<v8::Value> string);
 +    inline QString toString(v8::Handle<v8::String> string);
 +    static QString toStringStatic(v8::Handle<v8::Value>);
 +    static QString toStringStatic(v8::Handle<v8::String>);
 +    static inline bool startsWithUpper(v8::Handle<v8::String>);
 +
 +    QVariant toVariant(v8::Handle<v8::Value>, int typeHint);
 +    v8::Handle<v8::Value> fromVariant(const QVariant &);
 +    inline bool isVariant(v8::Handle<v8::Value>);
 +
 +    // Compile \a source (from \a fileName at \a lineNumber) in QML mode
 +    v8::Local<v8::Script> qmlModeCompile(const QString &source, 
 +                                         const QString &fileName = QString(), 
 +                                         int lineNumber = 1);
 +    v8::Local<v8::Script> qmlModeCompile(const char *source, int sourceLength = -1,
 +                                         const QString &fileName = QString(),
 +                                         int lineNumber = 1);
 +
 +    // Return the QML global "scope" object for the \a ctxt context and \a scope object.
 +    inline v8::Local<v8::Object> qmlScope(QQmlContextData *ctxt, QObject *scope);
 +
 +    // Return a JS wrapper for the given QObject \a object
 +    inline v8::Handle<v8::Value> newQObject(QObject *object);
 +    inline v8::Handle<v8::Value> newQObject(QObject *object, const ObjectOwnership ownership);
 +    inline bool isQObject(v8::Handle<v8::Value>);
 +    inline QObject *toQObject(v8::Handle<v8::Value>);
 +
 +    // Return a JS string for the given QString \a string
 +    inline v8::Local<v8::String> toString(const QString &string);
 +
 +    // Create a new value type object
 +    inline v8::Handle<v8::Value> newValueType(QObject *, int coreIndex, QQmlValueType *);
 +    inline v8::Handle<v8::Value> newValueType(const QVariant &, QQmlValueType *);
 +
 +    // Create a new sequence type object
 +    inline v8::Handle<v8::Value> newSequence(int sequenceType, QObject *, int coreIndex, bool *succeeded);
 +
 +    // Create a new QVariant object.  This doesn't examine the type of the variant, but always returns
 +    // a QVariant wrapper
 +    inline v8::Handle<v8::Value> newQVariant(const QVariant &);
 +
 +    // Return the network access manager for this engine.  By default this returns the network
 +    // access manager of the QQmlEngine.  It is overridden in the case of a threaded v8
 +    // instance (like in WorkerScript).
 +    virtual QNetworkAccessManager *networkAccessManager();
 +
 +    // Return the list of illegal id names (the names of the properties on the global object)
 +    const QStringHash<bool> &illegalNames() const;
 +
 +    inline void collectGarbage() { gc(); }
 +    static void gc();
 +
 +    void clearExceptions();
 +    void setException(v8::Handle<v8::Value> value, v8::Handle<v8::Message> message = v8::Handle<v8::Message>());
 +    v8::Handle<v8::Value> throwException(v8::Handle<v8::Value> value);
 +    bool hasUncaughtException() const;
 +    int uncaughtExceptionLineNumber() const;
 +    QStringList uncaughtExceptionBacktrace() const;
 +    v8::Handle<v8::Value> uncaughtException() const;
 +    void saveException();
 +    void restoreException();
 +
 +#ifdef QML_GLOBAL_HANDLE_DEBUGGING
 +    // Used for handle debugging
 +    static void registerHandle(void *);
 +    static void releaseHandle(void *);
 +#endif
 +
 +    static QMutex *registrationMutex();
 +    static int registerExtension();
 +
 +    inline Deletable *extensionData(int) const;
 +    void setExtensionData(int, Deletable *);
 +
 +    inline v8::Handle<v8::Value> makeJSValue(bool value);
 +    inline v8::Local<v8::Value> makeJSValue(int value);
 +    inline v8::Local<v8::Value> makeJSValue(uint value);
 +    inline v8::Local<v8::Value> makeJSValue(double value);
 +    inline v8::Handle<v8::Value> makeJSValue(QJSValue::SpecialValue value);
 +    inline v8::Local<v8::Value> makeJSValue(const QString &value);
 +
 +    inline QScriptPassPointer<QJSValuePrivate> evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
 +    QScriptPassPointer<QJSValuePrivate> evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch);
 +
 +    QScriptPassPointer<QJSValuePrivate> newArray(uint length);
 +    v8::Local<v8::Object> newVariant(const QVariant &variant);
 +
 +    v8::Local<v8::Array> variantListToJS(const QVariantList &lst);
 +    QVariantList variantListFromJS(v8::Handle<v8::Array> jsArray);
 +
 +    v8::Local<v8::Object> variantMapToJS(const QVariantMap &vmap);
 +    QVariantMap variantMapFromJS(v8::Handle<v8::Object> jsObject);
 +
 +    v8::Handle<v8::Value> variantToJS(const QVariant &value);
 +    QVariant variantFromJS(v8::Handle<v8::Value> value);
 +
 +    v8::Handle<v8::Value> metaTypeToJS(int type, const void *data);
 +    bool metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data);
 +
 +    bool convertToNativeQObject(v8::Handle<v8::Value> value,
 +                                const QByteArray &targetType,
 +                                void **result);
 +
 +    QVariant &variantValue(v8::Handle<v8::Value> value);
 +
 +    QJSValue scriptValueFromInternal(v8::Handle<v8::Value>) const;
 +
 +    void emitSignalHandlerException();
 +
 +    // used for console.time(), console.timeEnd()
 +    void startTimer(const QString &timerName);
 +    qint64 stopTimer(const QString &timerName, bool *wasRunning);
 +
 +    // used for console.count()
 +    int consoleCountHelper(const QString &file, int line, int column);
 +
 +    QObject *qtObjectFromJS(v8::Handle<v8::Value> value);
 +    QSet<int> visitedConversionObjects;
 +
 +    static QDateTime qtDateTimeFromJsDate(double jsDate);
 +
 +    void addRelationshipForGC(QObject *object, v8::Persistent<v8::Value> handle);
 +    void addRelationshipForGC(QObject *object, QObject *other);
 +
 +    struct ThreadData {
 +        ThreadData();
 +        ~ThreadData();
 +        v8::Isolate* isolate;
 +        bool gcPrologueCallbackRegistered;
 +        QIntrusiveList<QV8GCCallback::Node, &QV8GCCallback::Node::node> gcCallbackNodes;
 +    };
 +
 +    static bool hasThreadData();
 +    static ThreadData* threadData();
 +    static void ensurePerThreadIsolate();
 +
 +    v8::Persistent<v8::Object> m_strongReferencer;
 +
 +protected:
 +    QJSEngine* q;
 +    QQmlEngine *m_engine;
 +    bool m_ownsV8Context;
 +    v8::Persistent<v8::Context> m_context;
 +    QScriptOriginalGlobalObject m_originalGlobalObject;
 +
 +    QV8StringWrapper m_stringWrapper;
 +    QV8ContextWrapper m_contextWrapper;
 +    QV8QObjectWrapper m_qobjectWrapper;
 +    QV8TypeWrapper m_typeWrapper;
 +    QV8ListWrapper m_listWrapper;
 +    QV8VariantWrapper m_variantWrapper;
 +    QV8ValueTypeWrapper m_valueTypeWrapper;
 +    QV8SequenceWrapper m_sequenceWrapper;
 +
 +    v8::Persistent<v8::Function> m_getOwnPropertyNames;
 +    v8::Persistent<v8::Function> m_freezeObject;
 +
 +    void *m_xmlHttpRequestData;
 +
 +    QVector<Deletable *> m_extensionData;
 +    Deletable *m_listModelData;
 +
 +    QStringHash<bool> m_illegalNames;
 +
 +    Exception m_exception;
 +
 +    QElapsedTimer m_time;
 +    QHash<QString, qint64> m_startedTimers;
 +
 +    QHash<QString, quint32> m_consoleCount;
 +
 +    QVariant toBasicVariant(v8::Handle<v8::Value>);
 +
 +    void initializeGlobal(v8::Handle<v8::Object>);
 +
 +    double qtDateTimeToJsDate(const QDateTime &dt);
 +
 +private:
 +    static v8::Persistent<v8::Object> *findOwnerAndStrength(QObject *object, bool *shouldBeStrong);
 +
 +    typedef QScriptIntrusiveList<QJSValuePrivate, &QJSValuePrivate::m_node> ValueList;
 +    ValueList m_values;
 +    typedef QScriptIntrusiveList<QJSValueIteratorPrivate, &QJSValueIteratorPrivate::m_node> ValueIteratorList;
 +    ValueIteratorList m_valueIterators;
 +
 +    Q_DISABLE_COPY(QV8Engine)
 +};
 +
 +// Allocate a new Persistent handle.  *ALL* persistent handles in QML must be allocated
 +// using this method.
 +template<class T>
 +v8::Persistent<T> qPersistentNew(v8::Handle<T> that)
 +{
 +    v8::Persistent<T> rv = v8::Persistent<T>::New(that);
 +#ifdef QML_GLOBAL_HANDLE_DEBUGGING
 +    QV8Engine::registerHandle(*rv);
 +#endif
 +    return rv;
 +}
 +
 +// Register a Persistent handle that was returned to you by V8 (such as by
 +// v8::Context::New). This allows us to do handle tracking on these handles too.
 +template<class T>
 +void qPersistentRegister(v8::Persistent<T> handle)
 +{
 +#ifdef QML_GLOBAL_HANDLE_DEBUGGING
 +    QV8Engine::registerHandle(*handle);
 +#else
 +    Q_UNUSED(handle);
 +#endif
 +}
 +
 +// Dispose and clear a persistent handle.  *ALL* persistent handles in QML must be
 +// disposed using this method.
 +template<class T>
 +void qPersistentDispose(v8::Persistent<T> &that)
 +{
 +#ifdef QML_GLOBAL_HANDLE_DEBUGGING
 +    QV8Engine::releaseHandle(*that);
 +#endif
 +    that.Dispose();
 +    that.Clear();
 +}
 +
 +QString QV8Engine::toString(v8::Handle<v8::Value> string)
 +{
 +    return m_stringWrapper.toString(string->ToString());
 +}
 +
 +QString QV8Engine::toString(v8::Handle<v8::String> string)
 +{
 +    return m_stringWrapper.toString(string);
 +}
 +
 +bool QV8Engine::isVariant(v8::Handle<v8::Value> value)
 +{
 +    return m_variantWrapper.isVariant(value);
 +}
 +
 +v8::Local<v8::Object> QV8Engine::qmlScope(QQmlContextData *ctxt, QObject *scope)
 +{
 +    return m_contextWrapper.qmlScope(ctxt, scope);
 +}
 +
 +bool QV8Engine::isQObject(v8::Handle<v8::Value> obj)
 +{
 +    return obj->IsObject()?m_qobjectWrapper.isQObject(v8::Handle<v8::Object>::Cast(obj)):false;
 +}
 +
 +QObject *QV8Engine::toQObject(v8::Handle<v8::Value> obj)
 +{
 +    return obj->IsObject()?m_qobjectWrapper.toQObject(v8::Handle<v8::Object>::Cast(obj)):0;
 +}
 +
 +v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object)
 +{
 +    return m_qobjectWrapper.newQObject(object);
 +}
 +
 +v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object, const ObjectOwnership ownership)
 +{
 +    if (!object)
 +        return v8::Null();
 +
 +    v8::Handle<v8::Value> result = newQObject(object);
 +    QQmlData *ddata = QQmlData::get(object, true);
 +    if (ownership == JavaScriptOwnership && ddata) {
 +        ddata->indestructible = false;
 +        ddata->explicitIndestructibleSet = true;
 +    }
 +    return result;
 +}
 +
 +v8::Local<v8::String> QV8Engine::toString(const QString &string)
 +{
 +    return m_stringWrapper.toString(string);
 +}
 +
 +v8::Handle<v8::Value> QV8Engine::newValueType(QObject *object, int property, QQmlValueType *type)
 +{
 +    return m_valueTypeWrapper.newValueType(object, property, type);
 +}
 +
 +v8::Handle<v8::Value> QV8Engine::newValueType(const QVariant &value, QQmlValueType *type)
 +{
 +    return m_valueTypeWrapper.newValueType(value, type);
 +}
 +
 +v8::Handle<v8::Value> QV8Engine::newSequence(int sequenceType, QObject *object, int property, bool *succeeded)
 +{
 +    return m_sequenceWrapper.newSequence(sequenceType, object, property, succeeded);
 +}
 +
 +// XXX Can this be made more optimal?  It is called prior to resolving each and every 
 +// unqualified name in QV8ContextWrapper.
 +bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string)
 +{
 +    uint16_t c = string->GetCharacter(0);
 +    return (c >= 'A' && c <= 'Z') || 
 +           (c > 127 && QChar::category(c) == QChar::Letter_Uppercase);
 +}
 +
 +QV8Engine::Deletable *QV8Engine::extensionData(int index) const
 +{
 +    if (index < m_extensionData.count())
 +        return m_extensionData[index];
 +    else
 +        return 0;
 +}
 +
 +QT_END_NAMESPACE
 +
 +#endif // QQMLV8ENGINE_P_H
index b84ae33,0000000..78b2cb7
mode 100644,000000..100644
--- /dev/null
@@@ -1,2113 -1,0 +1,2113 @@@
-     if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) {
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qv8qobjectwrapper_p.h"
 +#include "qv8contextwrapper_p.h"
 +#include "qv8engine_p.h"
 +
 +#include <private/qqmlguard_p.h>
 +#include <private/qqmlpropertycache_p.h>
 +#include <private/qqmlengine_p.h>
 +#include <private/qqmlvmemetaobject_p.h>
 +#include <private/qqmlbinding_p.h>
 +#include <private/qjsvalue_p.h>
 +#include <private/qscript_impl_p.h>
 +#include <private/qqmlaccessors_p.h>
 +#include <private/qqmlexpression_p.h>
 +
 +#include <QtQml/qjsvalue.h>
 +#include <QtCore/qvarlengtharray.h>
 +#include <QtCore/qtimer.h>
 +#include <QtCore/qatomic.h>
 +
 +Q_DECLARE_METATYPE(QJSValue);
 +Q_DECLARE_METATYPE(QQmlV8Handle);
 +
 +QT_BEGIN_NAMESPACE
 +
 +#if defined(__GNUC__)
 +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
 +// The code in this file does not violate strict aliasing, but GCC thinks it does
 +// so turn off the warnings for us to have a clean build
 +#  pragma GCC diagnostic ignored "-Wstrict-aliasing"
 +# endif
 +#endif
 +
 +#define QOBJECT_TOSTRING_INDEX -2
 +#define QOBJECT_DESTROY_INDEX -3
 +
 +// XXX TODO: Need to review all calls to QQmlEngine *engine() to confirm QObjects work
 +// correctly in a worker thread
 +
 +class QV8QObjectResource : public QV8ObjectResource
 +{
 +    V8_RESOURCE_TYPE(QObjectType);
 +
 +public:
 +    QV8QObjectResource(QV8Engine *engine, QObject *object);
 +
 +    QQmlGuard<QObject> object;
 +};
 +
 +class QV8QObjectInstance : public QQmlGuard<QObject>
 +{
 +public:
 +    QV8QObjectInstance(QObject *o, QV8QObjectWrapper *w)
 +    : QQmlGuard<QObject>(o), wrapper(w)
 +    {
 +    }
 +
 +    ~QV8QObjectInstance()
 +    {
 +        qPersistentDispose(v8object);
 +    }
 +
 +    virtual void objectDestroyed(QObject *o)
 +    {
 +        if (wrapper)
 +            wrapper->m_taintedObjects.remove(o);
 +        delete this;
 +    }
 +
 +    v8::Persistent<v8::Object> v8object;
 +    QV8QObjectWrapper *wrapper;
 +};
 +
 +class QV8SignalHandlerResource : public QV8ObjectResource
 +{
 +    V8_RESOURCE_TYPE(SignalHandlerType)
 +public:
 +    QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index);
 +
 +    QQmlGuard<QObject> object;
 +    int index;
 +};
 +
 +namespace {
 +
 +template<typename A, typename B, typename C, typename D, typename E>
 +class MaxSizeOf5 {
 +    template<typename Z, typename X>
 +    struct SMax {
 +        static const size_t Size = sizeof(Z) > sizeof(X) ? sizeof(Z) : sizeof(X);
 +    };
 +public:
 +    static const size_t Size = SMax<A, SMax<B, SMax<C, SMax<D, E> > > >::Size;
 +};
 +
 +struct CallArgument {
 +    inline CallArgument();
 +    inline ~CallArgument();
 +    inline void *dataPtr();
 +
 +    inline void initAsType(int type);
 +    inline void fromValue(int type, QV8Engine *, v8::Handle<v8::Value>);
 +    inline v8::Handle<v8::Value> toValue(QV8Engine *);
 +
 +private:
 +    CallArgument(const CallArgument &);
 +
 +    inline void cleanup();
 +
 +    union {
 +        float floatValue;
 +        double doubleValue;
 +        quint32 intValue;
 +        bool boolValue;
 +        QObject *qobjectPtr;
 +
 +        char allocData[MaxSizeOf5<QVariant,
 +                                QString,
 +                                QList<QObject *>,
 +                                QJSValue,
 +                                QQmlV8Handle>::Size];
 +        qint64 q_for_alignment;
 +    };
 +
 +    // Pointers to allocData
 +    union {
 +        QString *qstringPtr;
 +        QVariant *qvariantPtr;
 +        QList<QObject *> *qlistPtr;
 +        QJSValue *qjsValuePtr;
 +        QQmlV8Handle *handlePtr;
 +    };
 +
 +    int type;
 +};
 +}
 +
 +QV8QObjectResource::QV8QObjectResource(QV8Engine *engine, QObject *object) 
 +: QV8ObjectResource(engine), object(object) 
 +{
 +}
 +
 +QV8SignalHandlerResource::QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index)
 +: QV8ObjectResource(engine), object(object), index(index)
 +{
 +}
 +
 +static QAtomicInt objectIdCounter(1);
 +
 +QV8QObjectWrapper::QV8QObjectWrapper()
 +: m_engine(0), m_id(objectIdCounter.fetchAndAddOrdered(1))
 +{
 +}
 +
 +QV8QObjectWrapper::~QV8QObjectWrapper()
 +{
 +    for (TaintedHash::Iterator iter = m_taintedObjects.begin(); 
 +         iter != m_taintedObjects.end();
 +         ++iter) {
 +        (*iter)->wrapper = 0;
 +    }
 +    m_taintedObjects.clear();
 +}
 +
 +void QV8QObjectWrapper::destroy()
 +{
 +    qDeleteAll(m_connections);
 +    m_connections.clear();
 +
 +    qPersistentDispose(m_hiddenObject);
 +    qPersistentDispose(m_destroySymbol);
 +    qPersistentDispose(m_toStringSymbol);
 +    qPersistentDispose(m_signalHandlerConstructor);
 +    qPersistentDispose(m_methodConstructor);
 +    qPersistentDispose(m_constructor);
 +}
 +
 +struct ReadAccessor {
 +    static inline void Indirect(QObject *object, const QQmlPropertyData &property,
 +                                void *output, QQmlNotifier **n)
 +    {
 +        Q_ASSERT(n == 0);
 +        Q_UNUSED(n);
 +
 +        void *args[] = { output, 0 };
 +        QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
 +    }
 +
 +    static inline void Direct(QObject *object, const QQmlPropertyData &property,
 +                              void *output, QQmlNotifier **n)
 +    {
 +        Q_ASSERT(n == 0);
 +        Q_UNUSED(n);
 +
 +        void *args[] = { output, 0 };
 +        object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args);
 +    }
 +
 +    static inline void Accessor(QObject *object, const QQmlPropertyData &property,
 +                                void *output, QQmlNotifier **n)
 +    {
 +        Q_ASSERT(property.accessors);
 +
 +        property.accessors->read(object, property.accessorData, output);
 +        if (n) property.accessors->notifier(object, property.accessorData, n);
 +    }
 +};
 +
 +static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, int v)
 +{ return v8::Integer::New(v); }
 +static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, uint v)
 +{ return v8::Integer::NewFromUnsigned(v); }
 +static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, bool v)
 +{ return v8::Boolean::New(v); }
 +static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *e, const QString &v)
 +{ return e->toString(v); }
 +static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, float v)
 +{ return v8::Number::New(v); }
 +static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, double v)
 +{ return v8::Number::New(v); }
 +static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *e, QObject *v)
 +{ return e->newQObject(v); }
 +
 +template<typename T, void (*ReadFunction)(QObject *, const QQmlPropertyData &,
 +                                          void *, QQmlNotifier **)>
 +static v8::Handle<v8::Value> GenericValueGetter(v8::Local<v8::String>, const v8::AccessorInfo &info)
 +{
 +    v8::Handle<v8::Object> This = info.This();
 +    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This);
 +
 +    QObject *object = resource->object;
 +    if (!object) return v8::Undefined();
 +
 +    QQmlPropertyData *property =
 +        (QQmlPropertyData *)v8::External::Unwrap(info.Data());
 +
 +    QQmlEngine *engine = resource->engine->engine();
 +    QQmlEnginePrivate *ep = engine?QQmlEnginePrivate::get(engine):0;
 +
 +    T value = T();
 +
 +    if (ep && ep->propertyCapture) {
 +        if (ReadFunction == ReadAccessor::Accessor && property->accessors->notifier) {
 +            QQmlNotifier *notifier = 0;
 +            ReadFunction(object, *property, &value, &notifier);
 +            if (notifier) ep->captureProperty(notifier);
 +        } else if (!property->isConstant()) {
 +            ep->captureProperty(object, property->coreIndex, property->notifyIndex);
 +            ReadFunction(object, *property, &value, 0);
 +        } else {
 +            ReadFunction(object, *property, &value, 0);
 +        }
 +    } else {
 +        ReadFunction(object, *property, &value, 0);
 +    }
 +
 +    return valueToHandle(resource->engine, value);
 +}
 +
 +#define FAST_GETTER_FUNCTION(property, cpptype) \
 +    (property->hasAccessors()?((v8::AccessorGetter)GenericValueGetter<cpptype, &ReadAccessor::Accessor>):(property->isDirect()?((v8::AccessorGetter)GenericValueGetter<cpptype, &ReadAccessor::Direct>):((v8::AccessorGetter)GenericValueGetter<cpptype, &ReadAccessor::Indirect>)))
 +
 +static quint32 toStringHash = -1;
 +static quint32 destroyHash = -1;
 +
 +void QV8QObjectWrapper::init(QV8Engine *engine)
 +{
 +    m_engine = engine;
 +
 +    m_toStringSymbol = qPersistentNew<v8::String>(v8::String::NewSymbol("toString"));
 +    m_destroySymbol = qPersistentNew<v8::String>(v8::String::NewSymbol("destroy"));
 +    m_hiddenObject = qPersistentNew<v8::Object>(v8::Object::New());
 +
 +    m_toStringString = QHashedV8String(m_toStringSymbol);
 +    m_destroyString = QHashedV8String(m_destroySymbol);
 +
 +    toStringHash = m_toStringString.hash();
 +    destroyHash = m_destroyString.hash();
 +
 +    {
 +    v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
 +    ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter, Query, 0, Enumerator);
 +    ft->InstanceTemplate()->SetHasExternalResource(true);
 +    m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
 +    }
 +    {
 +    v8::ScriptOrigin origin(m_hiddenObject); // Hack to allow us to identify these functions
 +#define CREATE_FUNCTION_SOURCE \
 +    "(function(method) { "\
 +        "return (function(object, data, qmlglobal) { "\
 +            "return (function() { "\
 +                "return method(object, data, qmlglobal, arguments.length, arguments); "\
 +            "});"\
 +        "});"\
 +    "})"
 +    v8::Local<v8::Script> script = v8::Script::New(v8::String::New(CREATE_FUNCTION_SOURCE), &origin, 0,
 +                                                   v8::Handle<v8::String>(), v8::Script::NativeMode);
 +#undef CREATE_FUNCTION_SOURCE
 +    v8::Local<v8::Function> fn = v8::Local<v8::Function>::Cast(script->Run());
 +    v8::Handle<v8::Value> invokeFn = v8::FunctionTemplate::New(Invoke)->GetFunction();
 +    v8::Handle<v8::Value> args[] = { invokeFn };
 +    v8::Local<v8::Function> createFn = v8::Local<v8::Function>::Cast(fn->Call(engine->global(), 1, args));
 +    m_methodConstructor = qPersistentNew<v8::Function>(createFn);
 +    }
 +
 +    v8::Local<v8::Function> connect = V8FUNCTION(Connect, engine);
 +    v8::Local<v8::Function> disconnect = V8FUNCTION(Disconnect, engine);
 +
 +    {
 +    v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
 +    ft->InstanceTemplate()->SetHasExternalResource(true);
 +    ft->PrototypeTemplate()->Set(v8::String::New("connect"), connect, v8::DontEnum);
 +    ft->PrototypeTemplate()->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum);
 +    m_signalHandlerConstructor = qPersistentNew<v8::Function>(ft->GetFunction());
 +    }
 +
 +    {
 +    v8::Local<v8::Object> prototype = engine->global()->Get(v8::String::New("Function"))->ToObject()->Get(v8::String::New("prototype"))->ToObject();
 +    prototype->Set(v8::String::New("connect"), connect, v8::DontEnum);
 +    prototype->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum);
 +    }
 +}
 +
 +bool QV8QObjectWrapper::isQObject(v8::Handle<v8::Object> obj)
 +{
 +    return v8_resource_cast<QV8QObjectResource>(obj) != 0;
 +}
 +
 +QObject *QV8QObjectWrapper::toQObject(v8::Handle<v8::Object> obj)
 +{
 +    QV8QObjectResource *r =  v8_resource_cast<QV8QObjectResource>(obj);
 +    return r?r->object:0;
 +}
 +
 +// r *MUST* be a QV8ObjectResource (r->type() == QV8ObjectResource::QObjectType)
 +QObject *QV8QObjectWrapper::toQObject(QV8ObjectResource *r)
 +{
 +    Q_ASSERT(r->resourceType() == QV8ObjectResource::QObjectType);
 +    return static_cast<QV8QObjectResource *>(r)->object;
 +}
 +
 +// Load value properties
 +template<void (*ReadFunction)(QObject *, const QQmlPropertyData &,
 +                              void *, QQmlNotifier **)>
 +static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object,
 +                                          const QQmlPropertyData &property,
 +                                          QQmlNotifier **notifier)
 +{
 +    Q_ASSERT(!property.isFunction());
 +
 +    if (property.isQObject()) {
 +        QObject *rv = 0;
 +        ReadFunction(object, property, &rv, notifier);
 +        return engine->newQObject(rv);
 +    } else if (property.isQList()) {
 +        return engine->listWrapper()->newList(object, property.coreIndex, property.propType);
 +    } else if (property.propType == QMetaType::QReal) {
 +        qreal v = 0;
 +        ReadFunction(object, property, &v, notifier);
 +        return valueToHandle(engine, v);
 +    } else if (property.propType == QMetaType::Int || property.isEnum()) {
 +        int v = 0;
 +        ReadFunction(object, property, &v, notifier);
 +        return valueToHandle(engine, v);
 +    } else if (property.propType == QMetaType::Bool) {
 +        bool v = false;
 +        ReadFunction(object, property, &v, notifier);
 +        return valueToHandle(engine, v);
 +    } else if (property.propType == QMetaType::QString) {
 +        QString v;
 +        ReadFunction(object, property, &v, notifier);
 +        return valueToHandle(engine, v);
 +    } else if (property.propType == QMetaType::UInt) {
 +        uint v = 0;
 +        ReadFunction(object, property, &v, notifier);
 +        return valueToHandle(engine, v);
 +    } else if (property.propType == QMetaType::Float) {
 +        float v = 0;
 +        ReadFunction(object, property, &v, notifier);
 +        return valueToHandle(engine, v);
 +    } else if (property.propType == QMetaType::Double) {
 +        double v = 0;
 +        ReadFunction(object, property, &v, notifier);
 +        return valueToHandle(engine, v);
 +    } else if (property.isV8Handle()) {
 +        QQmlV8Handle handle;
 +        ReadFunction(object, property, &handle, notifier);
 +        return handle.toHandle();
 +    } else if (property.isQVariant()) {
 +        QVariant v;
 +        ReadFunction(object, property, &v, notifier);
 +        return engine->fromVariant(v);
 +    } else if (QQmlValueTypeFactory::isValueType((uint)property.propType)
 +               && engine->engine()) {
 +        Q_ASSERT(notifier == 0);
 +
 +        QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->engine());
 +        QQmlValueType *valueType = ep->valueTypes[property.propType];
 +        if (valueType)
 +            return engine->newValueType(object, property.coreIndex, valueType);
 +    } else {
 +        Q_ASSERT(notifier == 0);
 +
 +        // see if it's a sequence type
 +        bool succeeded = false;
 +        v8::Handle<v8::Value> retn = engine->newSequence(property.propType, object, property.coreIndex,
 +                                                         &succeeded);
 +        if (succeeded)
 +            return retn;
 +    }
 +
 +    if (property.propType == QVariant::Invalid) {
 +        QMetaProperty p = object->metaObject()->property(property.coreIndex);
 +        qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property "
 +                 "'%s::%s'", p.typeName(), object->metaObject()->className(), p.name());
 +        return v8::Undefined();
 +    } else {
 +        QVariant v(property.propType, (void *)0);
 +        ReadFunction(object, property, v.data(), notifier);
 +        return engine->fromVariant(v);
 +    }
 +}
 +
 +v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject *object, 
 +                                                     v8::Handle<v8::Value> *objectHandle, 
 +                                                     const QHashedV8String &property,
 +                                                     QV8QObjectWrapper::RevisionMode revisionMode)
 +{
 +    // XXX More recent versions of V8 introduced "Callable" objects.  It is possible that these
 +    // will be a faster way of creating QObject method objects.
 +    struct MethodClosure {
 +       static v8::Handle<v8::Value> create(QV8Engine *engine, QObject *object, 
 +                                           v8::Handle<v8::Value> *objectHandle, 
 +                                           int index) { 
 +           v8::Handle<v8::Value> argv[] = { 
 +               objectHandle?*objectHandle:engine->newQObject(object),
 +               v8::Integer::New(index)
 +           };
 +           return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 2, argv);
 +       }
 +       static v8::Handle<v8::Value> createWithGlobal(QV8Engine *engine, QObject *object, 
 +                                                     v8::Handle<v8::Value> *objectHandle, 
 +                                                     int index) { 
 +           v8::Handle<v8::Value> argv[] = { 
 +               objectHandle?*objectHandle:engine->newQObject(object),
 +               v8::Integer::New(index),
 +               v8::Context::GetCallingQmlGlobal()
 +           };
 +           return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 3, argv);
 +       }
 +    };
 +
 +    {
 +        // Comparing the hash first actually makes a measurable difference here, at least on x86
 +        quint32 hash = property.hash();
 +        if (hash == toStringHash && engine->qobjectWrapper()->m_toStringString == property) {
 +            return MethodClosure::create(engine, object, objectHandle, QOBJECT_TOSTRING_INDEX);
 +        } else if (hash == destroyHash && engine->qobjectWrapper()->m_destroyString == property) {
 +            return MethodClosure::create(engine, object, objectHandle, QOBJECT_DESTROY_INDEX);
 +        }
 +    }
 +
 +    QQmlPropertyData local;
 +    QQmlPropertyData *result = 0;
 +    {
 +        QQmlData *ddata = QQmlData::get(object, false);
 +        if (ddata && ddata->propertyCache)
 +            result = ddata->propertyCache->property(property);
 +        else
 +            result = QQmlPropertyCache::property(engine->engine(), object, property, local);
 +    }
 +
 +    if (!result)
 +        return v8::Handle<v8::Value>();
 +
-     if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) {
++    if (revisionMode == QV8QObjectWrapper::CheckRevision && result->hasRevision()) {
 +        QQmlData *ddata = QQmlData::get(object);
 +        if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
 +            return v8::Handle<v8::Value>();
 +    }
 +
 +    if (result->isFunction()) {
 +        if (result->isVMEFunction()) {
 +            return ((QQmlVMEMetaObject *)(object->metaObject()))->vmeMethod(result->coreIndex);
 +        } else if (result->isV8Function()) {
 +            return MethodClosure::createWithGlobal(engine, object, objectHandle, result->coreIndex);
 +        } else if (result->isSignalHandler()) {
 +            v8::Local<v8::Object> handler = engine->qobjectWrapper()->m_signalHandlerConstructor->NewInstance();
 +            QV8SignalHandlerResource *r = new QV8SignalHandlerResource(engine, object, result->coreIndex);
 +            handler->SetExternalResource(r);
 +            return handler;
 +        } else {
 +            return MethodClosure::create(engine, object, objectHandle, result->coreIndex);
 +        }
 +    }
 +
 +    QQmlEnginePrivate *ep =
 +        engine->engine()?QQmlEnginePrivate::get(engine->engine()):0;
 +
 +    if (result->hasAccessors()) {
 +        QQmlNotifier *n = 0;
 +        QQmlNotifier **nptr = 0;
 +
 +        if (ep && ep->propertyCapture && result->accessors->notifier)
 +            nptr = &n;
 +
 +        v8::Handle<v8::Value> rv = LoadProperty<ReadAccessor::Accessor>(engine, object, *result, nptr);
 +
 +        if (result->accessors->notifier) {
 +            if (n) ep->captureProperty(n);
 +        } else {
 +            ep->captureProperty(object, result->coreIndex, result->notifyIndex);
 +        }
 +
 +        return rv;
 +    }
 +
 +    if (ep && !result->isConstant()) {
 +
 +        if (result->coreIndex == 0)
 +            ep->captureProperty(QQmlData::get(object, true)->objectNameNotifier());
 +        else
 +            ep->captureProperty(object, result->coreIndex, result->notifyIndex);
 +    }
 +
 +    if (result->isVMEProperty()) {
 +        typedef QQmlVMEMetaObject VMEMO;
 +        VMEMO *vmemo = const_cast<VMEMO *>(static_cast<const VMEMO *>(object->metaObject()));
 +        return vmemo->vmeProperty(result->coreIndex);
 +    } else if (result->isDirect())  {
 +        return LoadProperty<ReadAccessor::Direct>(engine, object, *result, 0);
 +    } else {
 +        return LoadProperty<ReadAccessor::Indirect>(engine, object, *result, 0);
 +    }
 +}
 +
 +// Setter for writable properties.  Shared between the interceptor and fast property accessor
 +static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropertyData *property,
 +                                 v8::Handle<v8::Value> value)
 +{
 +    QQmlBinding *newBinding = 0;
 +
 +    if (value->IsFunction()) {
 +        QQmlContextData *context = engine->callingContext();
 +        v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
 +
 +        v8::Local<v8::StackTrace> trace = 
 +            v8::StackTrace::CurrentStackTrace(1, (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber | 
 +                                                                                     v8::StackTrace::kScriptName));
 +        v8::Local<v8::StackFrame> frame = trace->GetFrame(0);
 +        int lineNumber = frame->GetLineNumber();
 +        int columNumber = frame->GetColumn();
 +        QString url = engine->toString(frame->GetScriptName());
 +
 +        newBinding = new QQmlBinding(&function, object, context);
 +        newBinding->setSourceLocation(url, lineNumber, columNumber);
 +        newBinding->setTarget(object, *property, context);
 +        newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
 +                                     QQmlBinding::RequiresThisObject);
 +    }
 +
 +    QQmlAbstractBinding *oldBinding = 
 +        QQmlPropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding);
 +    if (oldBinding)
 +        oldBinding->destroy();
 +
 +#define PROPERTY_STORE(cpptype, value) \
 +    cpptype o = value; \
 +    int status = -1; \
 +    int flags = 0; \
 +    void *argv[] = { &o, 0, &status, &flags }; \
 +    QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex, argv);
 +
 +
 +    if (value->IsNull() && property->isQObject()) {
 +        PROPERTY_STORE(QObject*, 0);
 +    } else if (value->IsUndefined() && property->isResettable()) {
 +        void *a[] = { 0 };
 +        QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex, a);
 +    } else if (value->IsUndefined() && property->propType == qMetaTypeId<QVariant>()) {
 +        PROPERTY_STORE(QVariant, QVariant());
 +    } else if (value->IsUndefined()) {
 +        QString error = QLatin1String("Cannot assign [undefined] to ") +
 +                        QLatin1String(QMetaType::typeName(property->propType));
 +        v8::ThrowException(v8::Exception::Error(engine->toString(error)));
 +    } else if (value->IsFunction()) {
 +        // this is handled by the binding creation above
 +    } else if (property->propType == QMetaType::Int && value->IsNumber()) {
 +        PROPERTY_STORE(int, qRound(value->ToNumber()->Value()));
 +    } else if (property->propType == QMetaType::QReal && value->IsNumber()) {
 +        PROPERTY_STORE(qreal, qreal(value->ToNumber()->Value()));
 +    } else if (property->propType == QMetaType::Float && value->IsNumber()) {
 +        PROPERTY_STORE(float, float(value->ToNumber()->Value()));
 +    } else if (property->propType == QMetaType::Double && value->IsNumber()) {
 +        PROPERTY_STORE(double, double(value->ToNumber()->Value()));
 +    } else if (property->propType == QMetaType::QString && value->IsString()) {
 +        PROPERTY_STORE(QString, engine->toString(value->ToString()));
 +    } else if (property->isVMEProperty()) {
 +        static_cast<QQmlVMEMetaObject *>(const_cast<QMetaObject *>(object->metaObject()))->setVMEProperty(property->coreIndex, value);
 +    } else {
 +        QVariant v;
 +        if (property->isQList()) 
 +            v = engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
 +        else
 +            v = engine->toVariant(value, property->propType);
 +
 +        QQmlContextData *context = engine->callingContext();
 +        if (!QQmlPropertyPrivate::write(object, *property, v, context)) {
 +            const char *valueType = 0;
 +            if (v.userType() == QVariant::Invalid) valueType = "null";
 +            else valueType = QMetaType::typeName(v.userType());
 +
 +            QString error = QLatin1String("Cannot assign ") +
 +                            QLatin1String(valueType) +
 +                            QLatin1String(" to ") +
 +                            QLatin1String(QMetaType::typeName(property->propType));
 +            v8::ThrowException(v8::Exception::Error(engine->toString(error)));
 +        }
 +    }
 +}
 +
 +bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, const QHashedV8String &property,
 +                                    v8::Handle<v8::Value> value, QV8QObjectWrapper::RevisionMode revisionMode)
 +{
 +    if (engine->qobjectWrapper()->m_toStringString == property ||
 +        engine->qobjectWrapper()->m_destroyString == property)
 +        return true;
 +
 +    QQmlPropertyData local;
 +    QQmlPropertyData *result = 0;
 +    result = QQmlPropertyCache::property(engine->engine(), object, property, local);
 +
 +    if (!result)
 +        return false;
 +
++    if (revisionMode == QV8QObjectWrapper::CheckRevision && result->hasRevision()) {
 +        QQmlData *ddata = QQmlData::get(object);
 +        if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
 +            return false;
 +    }
 +
 +    if (!result->isWritable() && !result->isQList()) {
 +        QString error = QLatin1String("Cannot assign to read-only property \"") +
 +                        engine->toString(property.string()) + QLatin1Char('\"');
 +        v8::ThrowException(v8::Exception::Error(engine->toString(error)));
 +        return true;
 +    }
 +
 +    StoreProperty(engine, object, result, value);
 +
 +    return true;
 +}
 +
 +v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property, 
 +                                                const v8::AccessorInfo &info)
 +{
 +    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 +
 +    if (resource->object.isNull()) 
 +        return v8::Handle<v8::Value>();
 +
 +    QObject *object = resource->object;
 +
 +    QHashedV8String propertystring(property);
 +
 +    QV8Engine *v8engine = resource->engine;
 +    v8::Handle<v8::Value> This = info.This();
 +    v8::Handle<v8::Value> result = GetProperty(v8engine, object, &This, propertystring, 
 +                                               QV8QObjectWrapper::IgnoreRevision);
 +    if (!result.IsEmpty())
 +        return result;
 +
 +    if (QV8Engine::startsWithUpper(property)) {
 +        // Check for attached properties
 +        QQmlContextData *context = v8engine->callingContext();
 +
 +        if (context && context->imports) {
 +            QQmlTypeNameCache::Result r = context->imports->query(propertystring);
 +
 +            if (r.isValid()) {
 +                if (r.scriptIndex != -1) {
 +                    return v8::Undefined();
 +                } else if (r.type) {
 +                    return v8engine->typeWrapper()->newObject(object, r.type, QV8TypeWrapper::ExcludeEnums);
 +                } else if (r.importNamespace) {
 +                    return v8engine->typeWrapper()->newObject(object, context->imports, r.importNamespace, 
 +                                                              QV8TypeWrapper::ExcludeEnums);
 +                }
 +                Q_ASSERT(!"Unreachable");
 +            }
 +        }
 +    } 
 +
 +    return v8::Handle<v8::Value>();
 +}
 +
 +v8::Handle<v8::Value> QV8QObjectWrapper::Setter(v8::Local<v8::String> property, 
 +                                                v8::Local<v8::Value> value,
 +                                                const v8::AccessorInfo &info)
 +{
 +    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 +
 +    if (resource->object.isNull()) 
 +        return value;
 +
 +    QObject *object = resource->object;
 +
 +    QHashedV8String propertystring(property);
 +
 +    QV8Engine *v8engine = resource->engine;
 +    bool result = SetProperty(v8engine, object, propertystring, value, QV8QObjectWrapper::IgnoreRevision);
 +
 +    if (!result) {
 +        QString error = QLatin1String("Cannot assign to non-existent property \"") +
 +                        v8engine->toString(property) + QLatin1Char('\"');
 +        v8::ThrowException(v8::Exception::Error(v8engine->toString(error)));
 +        return value;
 +    }
 +
 +    return value;
 +}
 +
 +v8::Handle<v8::Integer> QV8QObjectWrapper::Query(v8::Local<v8::String> property,
 +                                                 const v8::AccessorInfo &info)
 +{
 +    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 +
 +    if (resource->object.isNull()) 
 +        return v8::Handle<v8::Integer>();
 +
 +    QV8Engine *engine = resource->engine;
 +    QObject *object = resource->object;
 +
 +    QHashedV8String propertystring(property);
 +
 +    QQmlPropertyData local;
 +    QQmlPropertyData *result = 0;
 +    result = QQmlPropertyCache::property(engine->engine(), object, propertystring, local);
 +
 +    if (!result)
 +        return v8::Handle<v8::Integer>();
 +    else if (!result->isWritable() && !result->isQList())
 +        return v8::Integer::New(v8::ReadOnly | v8::DontDelete);
 +    else
 +        return v8::Integer::New(v8::DontDelete);
 +}
 +
 +v8::Handle<v8::Array> QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info)
 +{
 +    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 +
 +    if (resource->object.isNull()) 
 +        return v8::Array::New();
 +
 +    QObject *object = resource->object;
 +
 +    QStringList result;
 +
 +    QQmlEnginePrivate *ep = resource->engine->engine()
 +            ? QQmlEnginePrivate::get(resource->engine->engine())
 +            : 0;
 +
 +    QQmlPropertyCache *cache = 0;
 +    QQmlData *ddata = QQmlData::get(object);
 +    if (ddata)
 +        cache = ddata->propertyCache;
 +
 +    if (!cache) {
 +        cache = ep ? ep->cache(object) : 0;
 +        if (cache) {
 +            if (ddata) { cache->addref(); ddata->propertyCache = cache; }
 +        } else {
 +            // Not cachable - fall back to QMetaObject (eg. dynamic meta object)
 +            const QMetaObject *mo = object->metaObject();
 +            int pc = mo->propertyCount();
 +            int po = mo->propertyOffset();
 +            for (int i=po; i<pc; ++i)
 +                result << QString::fromUtf8(mo->property(i).name());
 +        }
 +    } else {
 +        result = cache->propertyNames();
 +    }
 +
 +    v8::Local<v8::Array> rv = v8::Array::New(result.count());
 +
 +    for (int ii = 0; ii < result.count(); ++ii) 
 +        rv->Set(ii, resource->engine->toString(result.at(ii)));
 +
 +    return rv;
 +}
 +
 +static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
 +                            const v8::AccessorInfo& info)
 +{
 +    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 +
 +    if (resource->object.isNull()) 
 +        return; 
 +
 +    QObject *object = resource->object;
 +
 +    QQmlPropertyData *property =
 +        (QQmlPropertyData *)v8::External::Unwrap(info.Data());
 +
 +    int index = property->coreIndex;
 +
 +    QQmlData *ddata = QQmlData::get(object, false);
 +    Q_ASSERT(ddata);
 +    Q_ASSERT(ddata->propertyCache);
 +
 +    QQmlPropertyData *pdata = ddata->propertyCache->property(index);
 +    Q_ASSERT(pdata);
 +
 +    Q_ASSERT(pdata->isWritable() || pdata->isQList());
 +
 +    StoreProperty(resource->engine, object, pdata, value);
 +}
 +
 +static void FastValueSetterReadOnly(v8::Local<v8::String> property, v8::Local<v8::Value>,
 +                                    const v8::AccessorInfo& info)
 +{
 +    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
 +
 +    if (resource->object.isNull()) 
 +        return; 
 +
 +    QV8Engine *v8engine = resource->engine;
 +
 +    QString error = QLatin1String("Cannot assign to read-only property \"") +
 +                    v8engine->toString(property) + QLatin1Char('\"');
 +    v8::ThrowException(v8::Exception::Error(v8engine->toString(error)));
 +}
 +
 +static void WeakQObjectReferenceCallback(v8::Persistent<v8::Value> handle, void *)
 +{
 +    Q_ASSERT(handle->IsObject());
 +    
 +    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(handle->ToObject());
 +
 +    Q_ASSERT(resource);
 +
 +    QObject *object = resource->object;
 +    if (object) {
 +        QQmlData *ddata = QQmlData::get(object, false);
 +        if (ddata) {
 +            ddata->v8object.Clear();
 +            if (!object->parent() && !ddata->indestructible)
 +                object->deleteLater();
 +        }
 +    }
 +
 +    qPersistentDispose(handle);
 +}
 +
 +static void WeakQObjectInstanceCallback(v8::Persistent<v8::Value> handle, void *data)
 +{
 +    QV8QObjectInstance *instance = (QV8QObjectInstance *)data;
 +    instance->v8object.Clear();
 +    qPersistentDispose(handle);
 +}
 +
 +v8::Local<v8::Object> QQmlPropertyCache::newQObject(QObject *object, QV8Engine *engine)
 +{
 +    Q_ASSERT(object);
 +    Q_ASSERT(this->engine);
 +
 +    Q_ASSERT(QQmlData::get(object, false));
 +    Q_ASSERT(QQmlData::get(object, false)->propertyCache == this);
 +
 +    // Setup constructor
 +    if (constructor.IsEmpty()) {
 +        v8::Local<v8::FunctionTemplate> ft;
 +
 +        QString toString = QLatin1String("toString");
 +        QString destroy = QLatin1String("destroy");
 +
 +        // As we use hash linking, it is possible that iterating over the values can give duplicates.
 +        // To combat this, we must unique'ify our properties.
 +        StringCache uniqueHash;
 +        if (stringCache.isLinked())
 +            uniqueHash.reserve(stringCache.count());
 +
 +        // XXX TODO: Enables fast property accessors.  These more than double the property access 
 +        // performance, but the  cost of setting up this structure hasn't been measured so 
 +        // its not guarenteed that this is a win overall.  We need to try and measure the cost.
 +        for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) {
 +            if (stringCache.isLinked()) {
 +                if (uniqueHash.contains(iter))
 +                    continue;
 +                uniqueHash.insert(iter);
 +            }
 +
 +            QQmlPropertyData *property = *iter;
 +            if (property->notFullyResolved()) resolve(property);
 +
 +            if (property->isFunction())
 +                continue;
 +
 +            v8::AccessorGetter fastgetter = 0;
 +            v8::AccessorSetter fastsetter = FastValueSetter;
 +            if (!property->isWritable())
 +                fastsetter = FastValueSetterReadOnly;
 +
 +            if (property->isQObject()) 
 +                fastgetter = FAST_GETTER_FUNCTION(property, QObject*);
 +            else if (property->propType == QMetaType::Int || property->isEnum()) 
 +                fastgetter = FAST_GETTER_FUNCTION(property, int);
 +            else if (property->propType == QMetaType::Bool)
 +                fastgetter = FAST_GETTER_FUNCTION(property, bool);
 +            else if (property->propType == QMetaType::QString)
 +                fastgetter = FAST_GETTER_FUNCTION(property, QString);
 +            else if (property->propType == QMetaType::UInt)
 +                fastgetter = FAST_GETTER_FUNCTION(property, uint);
 +            else if (property->propType == QMetaType::Float) 
 +                fastgetter = FAST_GETTER_FUNCTION(property, float);
 +            else if (property->propType == QMetaType::Double) 
 +                fastgetter = FAST_GETTER_FUNCTION(property, double);
 +
 +            if (fastgetter) {
 +                QString name = iter.key();
 +                if (name == toString || name == destroy)
 +                    continue;
 +
 +                if (ft.IsEmpty()) {
 +                    ft = v8::FunctionTemplate::New();
 +                    ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter, 
 +                                                                       QV8QObjectWrapper::Setter,
 +                                                                       QV8QObjectWrapper::Query, 
 +                                                                       0,
 +                                                                       QV8QObjectWrapper::Enumerator);
 +                    ft->InstanceTemplate()->SetHasExternalResource(true);
 +                }
 +
 +                // We wrap the raw QQmlPropertyData pointer here.  This is safe as the
 +                // pointer will remain valid at least as long as the lifetime of any QObject's of
 +                // this type and the property accessor checks if the object is 0 (deleted) before
 +                // dereferencing the pointer.
 +                ft->InstanceTemplate()->SetAccessor(engine->toString(name), fastgetter, fastsetter,
 +                                                    v8::External::Wrap(property));
 +            }
 +        }
 +
 +        if (ft.IsEmpty()) {
 +            constructor = qPersistentNew<v8::Function>(engine->qobjectWrapper()->m_constructor);
 +        } else {
 +            ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter, 
 +                                                               QV8QObjectWrapper::Setter,
 +                                                               QV8QObjectWrapper::Query, 
 +                                                               0,
 +                                                               QV8QObjectWrapper::Enumerator);
 +            ft->InstanceTemplate()->SetHasExternalResource(true);
 +            constructor = qPersistentNew<v8::Function>(ft->GetFunction());
 +        }
 +
 +        QQmlCleanup::addToEngine(this->engine);
 +    }
 +
 +    v8::Local<v8::Object> result = constructor->NewInstance();
 +    QV8QObjectResource *r = new QV8QObjectResource(engine, object);
 +    result->SetExternalResource(r);
 +    return result;
 +}
 +
 +v8::Local<v8::Object> QV8QObjectWrapper::newQObject(QObject *object, QQmlData *ddata, QV8Engine *engine)
 +{
 +    v8::Local<v8::Object> rv;
 +
 +    if (!ddata->propertyCache && engine->engine()) {
 +        ddata->propertyCache = QQmlEnginePrivate::get(engine->engine())->cache(object);
 +        if (ddata->propertyCache) ddata->propertyCache->addref();
 +    }
 +
 +    if (ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine->engine()) {
 +        rv = ddata->propertyCache->newQObject(object, engine);
 +    } else {
 +        // XXX NewInstance() should be optimized
 +        rv = m_constructor->NewInstance(); 
 +        QV8QObjectResource *r = new QV8QObjectResource(engine, object);
 +        rv->SetExternalResource(r);
 +    }
 +
 +    return rv;
 +}
 +
 +/*
 +As V8 doesn't support an equality callback, for QObject's we have to return exactly the same
 +V8 handle for subsequent calls to newQObject for the same QObject.  To do this we have a two
 +pronged strategy:
 +   1. If there is no current outstanding V8 handle to the QObject, we create one and store a 
 +      persistent handle in QQmlData::v8object.  We mark the QV8QObjectWrapper that 
 +      "owns" this handle by setting the QQmlData::v8objectid to the id of this 
 +      QV8QObjectWrapper.
 +   2. If another QV8QObjectWrapper has create the handle in QQmlData::v8object we create 
 +      an entry in the m_taintedObject hash where we store the handle and mark the object as 
 +      "tainted" in the QQmlData::hasTaintedV8Object flag.
 +We have to mark the object as tainted to ensure that we search our m_taintedObject hash even
 +in the case that the original QV8QObjectWrapper owner of QQmlData::v8object has 
 +released the handle.
 +*/
 +v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
 +{
 +    if (!object)
 +        return v8::Null();
 +
 +    if (QObjectPrivate::get(object)->wasDeleted)
 +       return v8::Undefined();
 +    
 +    QQmlData *ddata = QQmlData::get(object, true);
 +
 +    if (!ddata) 
 +        return v8::Undefined();
 +
 +    if (ddata->v8objectid == m_id && !ddata->v8object.IsEmpty()) {
 +        // We own the v8object 
 +        return v8::Local<v8::Object>::New(ddata->v8object);
 +    } else if (ddata->v8object.IsEmpty() && 
 +               (ddata->v8objectid == m_id || // We own the QObject
 +                ddata->v8objectid == 0 ||    // No one owns the QObject
 +                !ddata->hasTaintedV8Object)) { // Someone else has used the QObject, but it isn't tainted
 +
 +        v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine);
 +        ddata->v8object = qPersistentNew<v8::Object>(rv);
 +        ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback);
 +        ddata->v8objectid = m_id;
 +        return rv;
 +
 +    } else {
 +        // If this object is tainted, we have to check to see if it is in our
 +        // tainted object list
 +        TaintedHash::Iterator iter =
 +            ddata->hasTaintedV8Object?m_taintedObjects.find(object):m_taintedObjects.end();
 +        bool found = iter != m_taintedObjects.end();
 +
 +        // If our tainted handle doesn't exist or has been collected, and there isn't
 +        // a handle in the ddata, we can assume ownership of the ddata->v8object
 +        if ((!found || (*iter)->v8object.IsEmpty()) && ddata->v8object.IsEmpty()) {
 +            v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine);
 +            ddata->v8object = qPersistentNew<v8::Object>(rv);
 +            ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback);
 +            ddata->v8objectid = m_id;
 +
 +            if (found) {
 +                delete (*iter);
 +                m_taintedObjects.erase(iter);
 +            }
 +
 +            return rv;
 +        } else if (!found) {
 +            QV8QObjectInstance *instance = new QV8QObjectInstance(object, this);
 +            iter = m_taintedObjects.insert(object, instance);
 +            ddata->hasTaintedV8Object = true;
 +        }
 +
 +        if ((*iter)->v8object.IsEmpty()) {
 +            v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine);
 +            (*iter)->v8object = qPersistentNew<v8::Object>(rv);
 +            (*iter)->v8object.MakeWeak((*iter), WeakQObjectInstanceCallback);
 +        }
 +
 +        return v8::Local<v8::Object>::New((*iter)->v8object);
 +    }
 +}
 +
 +QPair<QObject *, int> QV8QObjectWrapper::ExtractQtSignal(QV8Engine *engine, v8::Handle<v8::Object> object)
 +{
 +    if (object->IsFunction())
 +        return ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(object));
 +
 +    if (QV8SignalHandlerResource *resource = v8_resource_cast<QV8SignalHandlerResource>(object))
 +        return qMakePair(resource->object.data(), resource->index);
 +
 +    return qMakePair((QObject *)0, -1);
 +}
 +
 +QPair<QObject *, int> QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, v8::Handle<v8::Function> function)
 +{
 +    v8::ScriptOrigin origin = function->GetScriptOrigin();
 +    if (origin.ResourceName()->StrictEquals(engine->qobjectWrapper()->m_hiddenObject)) {
 +
 +        // This is one of our special QObject method wrappers
 +        v8::Handle<v8::Value> args[] = { engine->qobjectWrapper()->m_hiddenObject };
 +        v8::Local<v8::Value> data = function->Call(engine->global(), 1, args);
 +
 +        if (data->IsArray()) {
 +            v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(data);
 +            return qMakePair(engine->toQObject(array->Get(0)), array->Get(1)->Int32Value());
 +        } 
 +
 +        // In theory this can't fall through, but I suppose V8 might run out of memory or something
 +    }
 +
 +    return qMakePair((QObject *)0, -1);
 +}
 +
 +class QV8QObjectConnectionList : public QObject, public QQmlGuard<QObject>
 +{
 +public:
 +    QV8QObjectConnectionList(QObject *object, QV8Engine *engine);
 +    ~QV8QObjectConnectionList();
 +
 +    struct Connection {
 +        Connection() 
 +        : needsDestroy(false) {}
 +        Connection(const Connection &other) 
 +        : thisObject(other.thisObject), function(other.function), needsDestroy(false) {}
 +        Connection &operator=(const Connection &other) {
 +            thisObject = other.thisObject;
 +            function = other.function;
 +            needsDestroy = other.needsDestroy;
 +            return *this;
 +        }
 +
 +        v8::Persistent<v8::Object> thisObject;
 +        v8::Persistent<v8::Function> function;
 +
 +        void dispose() {
 +            qPersistentDispose(thisObject);
 +            qPersistentDispose(function);
 +        }
 +
 +        bool needsDestroy;
 +    };
 +
 +    struct ConnectionList : public QList<Connection> {
 +        ConnectionList() : connectionsInUse(0), connectionsNeedClean(false) {}
 +        int connectionsInUse;
 +        bool connectionsNeedClean;
 +    };
 +
 +    QV8Engine *engine;
 +
 +    typedef QHash<int, ConnectionList> SlotHash;
 +    SlotHash slotHash;
 +    bool needsDestroy;
 +    int inUse;
 +
 +    virtual void objectDestroyed(QObject *);
 +    virtual int qt_metacall(QMetaObject::Call, int, void **);
 +};
 +
 +QV8QObjectConnectionList::QV8QObjectConnectionList(QObject *object, QV8Engine *engine)
 +: QQmlGuard<QObject>(object), engine(engine), needsDestroy(false), inUse(0)
 +{
 +}
 +
 +QV8QObjectConnectionList::~QV8QObjectConnectionList()
 +{
 +    for (SlotHash::Iterator iter = slotHash.begin(); iter != slotHash.end(); ++iter) {
 +        QList<Connection> &connections = *iter;
 +        for (int ii = 0; ii < connections.count(); ++ii) {
 +            qPersistentDispose(connections[ii].thisObject);
 +            qPersistentDispose(connections[ii].function);
 +        }
 +    }
 +    slotHash.clear();
 +}
 +
 +void QV8QObjectConnectionList::objectDestroyed(QObject *object)
 +{
 +    engine->qobjectWrapper()->m_connections.remove(object);
 +
 +    if (inUse)
 +        needsDestroy = true;
 +    else
 +        delete this;
 +}
 +
 +int QV8QObjectConnectionList::qt_metacall(QMetaObject::Call method, int index, void **metaArgs)
 +{
 +    if (method == QMetaObject::InvokeMetaMethod) {
 +        SlotHash::Iterator iter = slotHash.find(index);
 +        if (iter == slotHash.end())
 +            return -1;
 +        ConnectionList &connectionList = *iter;
 +        if (connectionList.isEmpty())
 +            return -1;
 +
 +        inUse++;
 +
 +        connectionList.connectionsInUse++;
 +
 +        QList<Connection> connections = connectionList;
 +
 +        QVarLengthArray<int, 9> dummy;
 +        int *argsTypes = QQmlPropertyCache::methodParameterTypes(data(), index, dummy, 0);
 +
 +        v8::HandleScope handle_scope;
 +        v8::Context::Scope scope(engine->context());
 +
 +        int argCount = argsTypes?argsTypes[0]:0;
 +        QVarLengthArray<v8::Handle<v8::Value>, 9> args(argCount);
 +
 +        for (int ii = 0; ii < argCount; ++ii) {
 +            int type = argsTypes[ii + 1];
 +            if (type == qMetaTypeId<QVariant>()) {
 +                args[ii] = engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
 +            } else {
 +                args[ii] = engine->fromVariant(QVariant(type, metaArgs[ii + 1]));
 +            }
 +        }
 +
 +        for (int ii = 0; ii < connections.count(); ++ii) {
 +            Connection &connection = connections[ii];
 +            if (connection.needsDestroy)
 +                continue;
 +
 +            v8::TryCatch try_catch;
 +            if (connection.thisObject.IsEmpty()) {
 +                connection.function->Call(engine->global(), argCount, args.data());
 +            } else {
 +                connection.function->Call(connection.thisObject, argCount, args.data());
 +            }
 +
 +            if (try_catch.HasCaught()) {
 +                QQmlError error;
 +                error.setDescription(QString(QLatin1String("Unknown exception occurred during evaluation of connected function: %1")).arg(engine->toString(connection.function->GetName())));
 +                v8::Local<v8::Message> message = try_catch.Message();
 +                if (!message.IsEmpty())
 +                    QQmlExpressionPrivate::exceptionToError(message, error);
 +                QQmlEnginePrivate::get(engine->engine())->warning(error);
 +            }
 +        }
 +
 +        connectionList.connectionsInUse--;
 +        if (connectionList.connectionsInUse == 0 && connectionList.connectionsNeedClean) {
 +            for (QList<Connection>::Iterator iter = connectionList.begin(); 
 +                 iter != connectionList.end(); ) {
 +                if (iter->needsDestroy) {
 +                    iter->dispose();
 +                    iter = connectionList.erase(iter);
 +                } else {
 +                    ++iter;
 +                }
 +            }
 +        }
 +
 +        inUse--;
 +        if (inUse == 0 && needsDestroy)
 +            delete this;
 +    } 
 +
 +    return -1;
 +}
 +
 +v8::Handle<v8::Value> QV8QObjectWrapper::Connect(const v8::Arguments &args)
 +{
 +    if (args.Length() == 0)
 +        V8THROW_ERROR("Function.prototype.connect: no arguments given");
 +
 +    QV8Engine *engine = V8ENGINE();
 +
 +    QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This());
 +    QObject *signalObject = signalInfo.first;
 +    int signalIndex = signalInfo.second;
 +
 +    if (signalIndex == -1)
 +        V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
 +
 +    if (!signalObject)
 +        V8THROW_ERROR("Function.prototype.connect: cannot connect to deleted QObject");
 +
 +    if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
 +        V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
 +
 +    v8::Local<v8::Value> functionValue;
 +    v8::Local<v8::Value> functionThisValue;
 +
 +    if (args.Length() == 1) {
 +        functionValue = args[0];
 +    } else {
 +        functionThisValue = args[0];
 +        functionValue = args[1];
 +    }
 +
 +    if (!functionValue->IsFunction())
 +        V8THROW_ERROR("Function.prototype.connect: target is not a function");
 +
 +    if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject())
 +        V8THROW_ERROR("Function.prototype.connect: target this is not an object");
 +
 +    QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
 +    QHash<QObject *, QV8QObjectConnectionList *> &connections = qobjectWrapper->m_connections;
 +    QHash<QObject *, QV8QObjectConnectionList *>::Iterator iter = connections.find(signalObject);
 +    if (iter == connections.end()) 
 +        iter = connections.insert(signalObject, new QV8QObjectConnectionList(signalObject, engine));
 +
 +    QV8QObjectConnectionList *connectionList = *iter;
 +    QV8QObjectConnectionList::SlotHash::Iterator slotIter = connectionList->slotHash.find(signalIndex);
 +    if (slotIter == connectionList->slotHash.end()) {
 +        slotIter = connectionList->slotHash.insert(signalIndex, QV8QObjectConnectionList::ConnectionList());
 +        QMetaObject::connect(signalObject, signalIndex, connectionList, signalIndex);
 +    }
 +
 +    QV8QObjectConnectionList::Connection connection;
 +    if (!functionThisValue.IsEmpty()) 
 +        connection.thisObject = qPersistentNew<v8::Object>(functionThisValue->ToObject());
 +    connection.function = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(functionValue));
 +
 +    slotIter->append(connection);
 +
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> QV8QObjectWrapper::Disconnect(const v8::Arguments &args)
 +{
 +    if (args.Length() == 0)
 +        V8THROW_ERROR("Function.prototype.disconnect: no arguments given");
 +
 +    QV8Engine *engine = V8ENGINE();
 +
 +    QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This());
 +    QObject *signalObject = signalInfo.first;
 +    int signalIndex = signalInfo.second;
 +
 +    if (signalIndex == -1)
 +        V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
 +
 +    if (!signalObject)
 +        V8THROW_ERROR("Function.prototype.disconnect: cannot disconnect from deleted QObject");
 +
 +    if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
 +        V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
 +
 +    v8::Local<v8::Value> functionValue;
 +    v8::Local<v8::Value> functionThisValue;
 +
 +    if (args.Length() == 1) {
 +        functionValue = args[0];
 +    } else {
 +        functionThisValue = args[0];
 +        functionValue = args[1];
 +    }
 +
 +    if (!functionValue->IsFunction())
 +        V8THROW_ERROR("Function.prototype.disconnect: target is not a function");
 +
 +    if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject())
 +        V8THROW_ERROR("Function.prototype.disconnect: target this is not an object");
 +
 +    QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
 +    QHash<QObject *, QV8QObjectConnectionList *> &connectionsList = qobjectWrapper->m_connections;
 +    QHash<QObject *, QV8QObjectConnectionList *>::Iterator iter = connectionsList.find(signalObject);
 +    if (iter == connectionsList.end()) 
 +        return v8::Undefined(); // Nothing to disconnect from
 +
 +    QV8QObjectConnectionList *connectionList = *iter;
 +    QV8QObjectConnectionList::SlotHash::Iterator slotIter = connectionList->slotHash.find(signalIndex);
 +    if (slotIter == connectionList->slotHash.end()) 
 +        return v8::Undefined(); // Nothing to disconnect from
 +
 +    QV8QObjectConnectionList::ConnectionList &connections = *slotIter;
 +
 +    v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(functionValue);
 +    QPair<QObject *, int> functionData = ExtractQtMethod(engine, function);
 +
 +    if (functionData.second != -1) {
 +        // This is a QObject function wrapper
 +        for (int ii = 0; ii < connections.count(); ++ii) {
 +            QV8QObjectConnectionList::Connection &connection = connections[ii];
 +
 +            if (connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() &&
 +                (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) {
 +
 +                QPair<QObject *, int> connectedFunctionData = ExtractQtMethod(engine, connection.function);
 +                if (connectedFunctionData == functionData) {
 +                    // Match!
 +                    if (connections.connectionsInUse) {
 +                        connection.needsDestroy = true;
 +                        connections.connectionsNeedClean = true;
 +                    } else {
 +                        connection.dispose();
 +                        connections.removeAt(ii);
 +                    }
 +                    return v8::Undefined();
 +                }
 +            }
 +        }
 +
 +    } else {
 +        // This is a normal JS function
 +        for (int ii = 0; ii < connections.count(); ++ii) {
 +            QV8QObjectConnectionList::Connection &connection = connections[ii];
 +            if (connection.function->StrictEquals(function) &&
 +                connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() &&
 +                (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) {
 +                // Match!
 +                if (connections.connectionsInUse) {
 +                    connection.needsDestroy = true;
 +                    connections.connectionsNeedClean = true;
 +                } else {
 +                    connection.dispose();
 +                    connections.removeAt(ii);
 +                }
 +                return v8::Undefined();
 +            }
 +        }
 +    }
 +
 +    return v8::Undefined();
 +}
 +
 +/*!
 +    \fn v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, const QHashedV8String &property, QV8QObjectWrapper::RevisionMode revisionMode)
 +
 +    Get the \a property of \a object.  Returns an empty handle if the property doesn't exist.
 +
 +    Only searches for real properties of \a object (including methods), not attached properties etc.
 +*/
 +
 +/*
 +    \fn bool QV8QObjectWrapper::setProperty(QObject *object, const QHashedV8String &property, v8::Handle<v8::Value> value, RevisionMode revisionMode)
 +
 +    Set the \a property of \a object to \a value.
 +
 +    Returns true if the property was "set" - even if this results in an exception being thrown -
 +    and false if the object has no such property.
 +
 +    Only searches for real properties of \a object (including methods), not attached properties etc.
 +*/
 +
 +namespace {
 +struct CallArgs
 +{
 +    CallArgs(int length, v8::Handle<v8::Object> *args) : _length(length), _args(args) {}
 +    int Length() const { return _length; }
 +    v8::Local<v8::Value> operator[](int idx) { return (*_args)->Get(idx); }
 +
 +private:
 +    int _length;
 +    v8::Handle<v8::Object> *_args;
 +};
 +}
 +
 +static v8::Handle<v8::Value> CallMethod(QObject *object, int index, int returnType, int argCount, 
 +                                        int *argTypes, QV8Engine *engine, CallArgs &callArgs)
 +{
 +    if (argCount > 0) {
 +
 +        QVarLengthArray<CallArgument, 9> args(argCount + 1);
 +        args[0].initAsType(returnType);
 +
 +        for (int ii = 0; ii < argCount; ++ii)
 +            args[ii + 1].fromValue(argTypes[ii], engine, callArgs[ii]);
 +
 +        QVarLengthArray<void *, 9> argData(args.count());
 +        for (int ii = 0; ii < args.count(); ++ii)
 +            argData[ii] = args[ii].dataPtr();
 +
 +        QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data());
 +
 +        return args[0].toValue(engine);
 +
 +    } else if (returnType != 0) {
 +        
 +        CallArgument arg;
 +        arg.initAsType(returnType);
 +
 +        void *args[] = { arg.dataPtr() };
 +
 +        QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
 +
 +        return arg.toValue(engine);
 +
 +    } else {
 +
 +        void *args[] = { 0 };
 +        QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
 +        return v8::Undefined();
 +
 +    }
 +}
 +
 +/*!
 +    Returns the match score for converting \a actual to be of type \a conversionType.  A 
 +    zero score means "perfect match" whereas a higher score is worse.
 +
 +    The conversion table is copied out of the QtScript callQtMethod() function.
 +*/
 +static int MatchScore(v8::Handle<v8::Value> actual, int conversionType)
 +{
 +    if (actual->IsNumber()) {
 +        switch (conversionType) {
 +        case QMetaType::Double:
 +            return 0;
 +        case QMetaType::Float:
 +            return 1;
 +        case QMetaType::LongLong:
 +        case QMetaType::ULongLong:
 +            return 2;
 +        case QMetaType::Long:
 +        case QMetaType::ULong:
 +            return 3;
 +        case QMetaType::Int:
 +        case QMetaType::UInt:
 +            return 4;
 +        case QMetaType::Short:
 +        case QMetaType::UShort:
 +            return 5;
 +            break;
 +        case QMetaType::Char:
 +        case QMetaType::UChar:
 +            return 6;
 +        default:
 +            return 10;
 +        }
 +    } else if (actual->IsString()) {
 +        switch (conversionType) {
 +        case QMetaType::QString:
 +            return 0;
 +        default:
 +            return 10;
 +        }
 +    } else if (actual->IsBoolean()) {
 +        switch (conversionType) {
 +        case QMetaType::Bool:
 +            return 0;
 +        default:
 +            return 10;
 +        }
 +    } else if (actual->IsDate()) {
 +        switch (conversionType) {
 +        case QMetaType::QDateTime:
 +            return 0;
 +        case QMetaType::QDate:
 +            return 1;
 +        case QMetaType::QTime:
 +            return 2;
 +        default:
 +            return 10;
 +        }
 +    } else if (actual->IsRegExp()) {
 +        switch (conversionType) {
 +        case QMetaType::QRegExp:
 +            return 0;
 +        default:
 +            return 10;
 +        }
 +    } else if (actual->IsArray()) {
 +        switch (conversionType) {
 +        case QMetaType::QStringList:
 +        case QMetaType::QVariantList:
 +            return 5;
 +        default:
 +            return 10;
 +        }
 +    } else if (actual->IsNull()) {
 +        switch (conversionType) {
 +        case QMetaType::VoidStar:
 +        case QMetaType::QObjectStar:
 +            return 0;
 +        default: {
 +            const char *typeName = QMetaType::typeName(conversionType);
 +            if (typeName && typeName[strlen(typeName) - 1] == '*')
 +                return 0;
 +            else
 +                return 10;
 +        }
 +        }
 +    } else if (actual->IsObject()) {
 +        v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(actual);
 +
 +        QV8ObjectResource *r = static_cast<QV8ObjectResource *>(obj->GetExternalResource());
 +        if (r && r->resourceType() == QV8ObjectResource::QObjectType) {
 +            switch (conversionType) {
 +            case QMetaType::QObjectStar:
 +                return 0;
 +            default:
 +                return 10;
 +            }
 +        } else if (r && r->resourceType() == QV8ObjectResource::VariantType) {
 +            if (conversionType == qMetaTypeId<QVariant>())
 +                return 0;
 +            else if (r->engine->toVariant(actual, -1).userType() == conversionType)
 +                return 0;
 +            else
 +                return 10;
 +        } else {
 +            return 10;
 +        }
 +
 +    } else {
 +        return 10;
 +    }
 +}
 +
 +static inline int QMetaObject_methods(const QMetaObject *metaObject)
 +{
 +    struct Private
 +    {
 +        int revision;
 +        int className;
 +        int classInfoCount, classInfoData;
 +        int methodCount, methodData;
 +    };
 +
 +    return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount;
 +}
 +
 +static QByteArray QMetaMethod_name(const QMetaMethod &m)
 +{
 +    QByteArray sig = m.signature();
 +    int paren = sig.indexOf('(');
 +    if (paren == -1)
 +        return sig;
 +    else
 +        return sig.left(paren);
 +}
 +
 +/*!
 +Returns the next related method, if one, or 0.
 +*/
 +static const QQmlPropertyData * RelatedMethod(QObject *object,
 +                                                      const QQmlPropertyData *current,
 +                                                      QQmlPropertyData &dummy)
 +{
 +    QQmlPropertyCache *cache = QQmlData::get(object)->propertyCache;
 +    if (!current->isOverload())
 +        return 0;
 +
 +    Q_ASSERT(!current->overrideIndexIsProperty);
 +
 +    if (cache) {
 +        return cache->method(current->overrideIndex);
 +    } else {
 +        const QMetaObject *mo = object->metaObject();
 +        int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
 +
 +        while (methodOffset > current->overrideIndex) {
 +            mo = mo->superClass();
 +            methodOffset -= QMetaObject_methods(mo);
 +        }
 +
 +        QMetaMethod method = mo->method(current->overrideIndex);
 +        dummy.load(method);
 +        
 +        // Look for overloaded methods
 +        QByteArray methodName = QMetaMethod_name(method);
 +        for (int ii = current->overrideIndex - 1; ii >= methodOffset; --ii) {
 +            if (methodName == QMetaMethod_name(mo->method(ii))) {
 +                dummy.setFlags(dummy.getFlags() | QQmlPropertyData::IsOverload);
 +                dummy.overrideIndexIsProperty = 0;
 +                dummy.overrideIndex = ii;
 +                return &dummy;
 +            }
 +        }
 +
 +        return &dummy;
 +    }
 +}
 +
 +static v8::Handle<v8::Value> CallPrecise(QObject *object, const QQmlPropertyData &data,
 +                                         QV8Engine *engine, CallArgs &callArgs)
 +{
 +    if (data.hasArguments()) {
 +
 +        int *args = 0;
 +        QVarLengthArray<int, 9> dummy;
 +        QByteArray unknownTypeError;
 +
 +        args = QQmlPropertyCache::methodParameterTypes(object, data.coreIndex, dummy, 
 +                                                               &unknownTypeError);
 +
 +        if (!args) {
 +            QString typeName = QString::fromLatin1(unknownTypeError);
 +            QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName);
 +            v8::ThrowException(v8::Exception::Error(engine->toString(error)));
 +            return v8::Handle<v8::Value>();
 +        }
 +
 +        if (args[0] > callArgs.Length()) {
 +            QString error = QLatin1String("Insufficient arguments");
 +            v8::ThrowException(v8::Exception::Error(engine->toString(error)));
 +            return v8::Handle<v8::Value>();
 +        }
 +
 +        return CallMethod(object, data.coreIndex, data.propType, args[0], args + 1, engine, callArgs);
 +
 +    } else {
 +
 +        return CallMethod(object, data.coreIndex, data.propType, 0, 0, engine, callArgs);
 +
 +    }
 +}
 +
 +/*!
 +Resolve the overloaded method to call.  The algorithm works conceptually like this:
 +    1.  Resolve the set of overloads it is *possible* to call.
 +        Impossible overloads include those that have too many parameters or have parameters 
 +        of unknown type.  
 +    2.  Filter the set of overloads to only contain those with the closest number of 
 +        parameters.
 +        For example, if we are called with 3 parameters and there are 2 overloads that
 +        take 2 parameters and one that takes 3, eliminate the 2 parameter overloads.
 +    3.  Find the best remaining overload based on its match score.  
 +        If two or more overloads have the same match score, call the last one.  The match
 +        score is constructed by adding the matchScore() result for each of the parameters.
 +*/
 +static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QQmlPropertyData &data,
 +                                            QV8Engine *engine, CallArgs &callArgs)
 +{
 +    int argumentCount = callArgs.Length();
 +
 +    const QQmlPropertyData *best = 0;
 +    int bestParameterScore = INT_MAX;
 +    int bestMatchScore = INT_MAX;
 +
 +    QQmlPropertyData dummy;
 +    const QQmlPropertyData *attempt = &data;
 +
 +    do {
 +        QVarLengthArray<int, 9> dummy;
 +        int methodArgumentCount = 0;
 +        int *methodArgTypes = 0;
 +        if (attempt->hasArguments()) {
 +            typedef QQmlPropertyCache PC;
 +            int *args = PC::methodParameterTypes(object, attempt->coreIndex, dummy, 0);
 +            if (!args) // Must be an unknown argument
 +                continue;
 +
 +            methodArgumentCount = args[0];
 +            methodArgTypes = args + 1;
 +        }
 +
 +        if (methodArgumentCount > argumentCount)
 +            continue; // We don't have sufficient arguments to call this method
 +
 +        int methodParameterScore = argumentCount - methodArgumentCount;
 +        if (methodParameterScore > bestParameterScore)
 +            continue; // We already have a better option
 +
 +        int methodMatchScore = 0;
 +        for (int ii = 0; ii < methodArgumentCount; ++ii) 
 +            methodMatchScore += MatchScore(callArgs[ii], methodArgTypes[ii]);
 +
 +        if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
 +            best = attempt;
 +            bestParameterScore = methodParameterScore;
 +            bestMatchScore = methodMatchScore;
 +        }
 +
 +        if (bestParameterScore == 0 && bestMatchScore == 0)
 +            break; // We can't get better than that
 +
 +    } while((attempt = RelatedMethod(object, attempt, dummy)) != 0);
 +
 +    if (best) {
 +        return CallPrecise(object, *best, engine, callArgs);
 +    } else {
 +        QString error = QLatin1String("Unable to determine callable overload.  Candidates are:");
 +        const QQmlPropertyData *candidate = &data;
 +        while (candidate) {
 +            error += QLatin1String("\n    ") + 
 +                     QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).signature());
 +            candidate = RelatedMethod(object, candidate, dummy);
 +        }
 +
 +        v8::ThrowException(v8::Exception::Error(engine->toString(error)));
 +        return v8::Handle<v8::Value>();
 +    }
 +}
 +
 +static v8::Handle<v8::Value> ToString(QV8Engine *engine, QObject *object, int, v8::Handle<v8::Object>)
 +{
 +    QString result;
 +    if (object) {
 +        QString objectName = object->objectName();
 +
 +        result += QString::fromUtf8(object->metaObject()->className());
 +        result += QLatin1String("(0x");
 +        result += QString::number((quintptr)object,16);
 +
 +        if (!objectName.isEmpty()) {
 +            result += QLatin1String(", \"");
 +            result += objectName;
 +            result += QLatin1Char('\"');
 +        }
 +
 +        result += QLatin1Char(')');
 +    } else {
 +        result = QLatin1String("null");
 +    }
 +
 +    return engine->toString(result);
 +}
 +
 +static v8::Handle<v8::Value> Destroy(QV8Engine *, QObject *object, int argCount, v8::Handle<v8::Object> args)
 +{
 +    QQmlData *ddata = QQmlData::get(object, false);
 +    if (!ddata || ddata->indestructible) {
 +        const char *error = "Invalid attempt to destroy() an indestructible object";
 +        v8::ThrowException(v8::Exception::Error(v8::String::New(error)));
 +        return v8::Undefined();
 +    }
 +
 +    int delay = 0;
 +    if (argCount > 0)
 +        delay = args->Get(0)->Uint32Value();
 +
 +    if (delay > 0)
 +        QTimer::singleShot(delay, object, SLOT(deleteLater()));
 +    else
 +        object->deleteLater();
 +
 +    return v8::Undefined();
 +}
 +
 +v8::Handle<v8::Value> QV8QObjectWrapper::Invoke(const v8::Arguments &args)
 +{
 +    // object, index, qmlglobal, argCount, args
 +    Q_ASSERT(args.Length() == 5);
 +    Q_ASSERT(args[0]->IsObject());
 +
 +    QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(args[0]->ToObject());
 +
 +    if (!resource)
 +        return v8::Undefined();
 +
 +    int argCount = args[3]->Int32Value();
 +    v8::Handle<v8::Object> arguments = v8::Handle<v8::Object>::Cast(args[4]);
 +
 +    // Special hack to return info about this closure.
 +    if (argCount == 1 && arguments->Get(0)->StrictEquals(resource->engine->qobjectWrapper()->m_hiddenObject)) {
 +        v8::Local<v8::Array> data = v8::Array::New(2);
 +        data->Set(0, args[0]);
 +        data->Set(1, args[1]);
 +        return data;
 +    }
 +
 +    QObject *object = resource->object;
 +    int index = args[1]->Int32Value();
 +
 +    if (!object)
 +        return v8::Undefined();
 +
 +    if (index < 0) {
 +        // Builtin functions
 +        if (index == QOBJECT_TOSTRING_INDEX) {
 +            return ToString(resource->engine, object, argCount, arguments);
 +        } else if (index == QOBJECT_DESTROY_INDEX) {
 +            return Destroy(resource->engine, object, argCount, arguments);
 +        } else {
 +            return v8::Undefined();
 +        }
 +    }
 +
 +    QQmlPropertyData method;
 +
 +    if (QQmlData *ddata = static_cast<QQmlData *>(QObjectPrivate::get(object)->declarativeData)) {
 +        if (ddata->propertyCache) {
 +            QQmlPropertyData *d = ddata->propertyCache->method(index);
 +            if (!d) 
 +                return v8::Undefined();
 +            method = *d;
 +        } 
 +    }
 +
 +    if (method.coreIndex == -1) {
 +        method.load(object->metaObject()->method(index));
 +
 +        if (method.coreIndex == -1)
 +            return v8::Undefined();
 +    }
 +
 +    if (method.isV8Function()) {
 +        v8::Handle<v8::Value> rv;
 +        v8::Handle<v8::Object> qmlglobal = args[2]->ToObject();
 +
 +        QQmlV8Function func(argCount, arguments, rv, qmlglobal, 
 +                                    resource->engine->contextWrapper()->context(qmlglobal),
 +                                    resource->engine);
 +        QQmlV8Function *funcptr = &func;
 +
 +        void *args[] = { 0, &funcptr };
 +        QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method.coreIndex, args);
 +
 +        if (rv.IsEmpty()) return v8::Undefined();
 +        return rv;
 +    }
 +
 +    CallArgs callArgs(argCount, &arguments);
 +    if (!method.isOverload()) {
 +        return CallPrecise(object, method, resource->engine, callArgs);
 +    } else {
 +        return CallOverloaded(object, method, resource->engine, callArgs);
 +    }
 +}
 +
 +CallArgument::CallArgument()
 +: type(QVariant::Invalid)
 +{
 +}
 +
 +CallArgument::~CallArgument()
 +{
 +    cleanup();
 +}
 +
 +void CallArgument::cleanup()
 +{
 +    if (type == QMetaType::QString) {
 +        qstringPtr->~QString();
 +    } else if (type == -1 || type == QMetaType::QVariant) {
 +        qvariantPtr->~QVariant();
 +    } else if (type == qMetaTypeId<QJSValue>()) {
 +        qjsValuePtr->~QJSValue();
 +    } else if (type == qMetaTypeId<QList<QObject *> >()) {
 +        qlistPtr->~QList<QObject *>();
 +    } 
 +}
 +
 +void *CallArgument::dataPtr()
 +{
 +    if (type == -1)
 +        return qvariantPtr->data();
 +    else
 +        return (void *)&allocData;
 +}
 +
 +void CallArgument::initAsType(int callType)
 +{
 +    if (type != 0) { cleanup(); type = 0; }
 +    if (callType == 0) return;
 +
 +    if (callType == qMetaTypeId<QJSValue>()) {
 +        qjsValuePtr = new (&allocData) QJSValue();
 +        type = callType;
 +    } else if (callType == QMetaType::Int ||
 +               callType == QMetaType::UInt ||
 +               callType == QMetaType::Bool ||
 +               callType == QMetaType::Double ||
 +               callType == QMetaType::Float) {
 +        type = callType;
 +    } else if (callType == QMetaType::QObjectStar) {
 +        qobjectPtr = 0;
 +        type = callType;
 +    } else if (callType == QMetaType::QString) {
 +        qstringPtr = new (&allocData) QString();
 +        type = callType;
 +    } else if (callType == QMetaType::QVariant) {
 +        type = callType;
 +        qvariantPtr = new (&allocData) QVariant();
 +    } else if (callType == qMetaTypeId<QList<QObject *> >()) {
 +        type = callType;
 +        qlistPtr = new (&allocData) QList<QObject *>();
 +    } else if (callType == qMetaTypeId<QQmlV8Handle>()) {
 +        type = callType;
 +        handlePtr = new (&allocData) QQmlV8Handle;
 +    } else {
 +        type = -1;
 +        qvariantPtr = new (&allocData) QVariant(callType, (void *)0);
 +    }
 +}
 +
 +void CallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Value> value)
 +{
 +    if (type != 0) { cleanup(); type = 0; }
 +
 +    if (callType == qMetaTypeId<QJSValue>()) {
 +        qjsValuePtr = new (&allocData) QJSValue(QJSValuePrivate::get(new QJSValuePrivate(engine, value)));
 +        type = qMetaTypeId<QJSValue>();
 +    } else if (callType == QMetaType::Int) {
 +        intValue = quint32(value->Int32Value());
 +        type = callType;
 +    } else if (callType == QMetaType::UInt) {
 +        intValue = quint32(value->Uint32Value());
 +        type = callType;
 +    } else if (callType == QMetaType::Bool) {
 +        boolValue = value->BooleanValue();
 +        type = callType;
 +    } else if (callType == QMetaType::Double) {
 +        doubleValue = double(value->NumberValue());
 +        type = callType;
 +    } else if (callType == QMetaType::Float) {
 +        floatValue = float(value->NumberValue());
 +        type = callType;
 +    } else if (callType == QMetaType::QString) {
 +        if (value->IsNull() || value->IsUndefined())
 +            qstringPtr = new (&allocData) QString();
 +        else
 +            qstringPtr = new (&allocData) QString(engine->toString(value->ToString()));
 +        type = callType;
 +    } else if (callType == QMetaType::QObjectStar) {
 +        qobjectPtr = engine->toQObject(value);
 +        type = callType;
 +    } else if (callType == qMetaTypeId<QVariant>()) {
 +        qvariantPtr = new (&allocData) QVariant(engine->toVariant(value, -1));
 +        type = callType;
 +    } else if (callType == qMetaTypeId<QList<QObject*> >()) {
 +        qlistPtr = new (&allocData) QList<QObject *>();
 +        if (value->IsArray()) {
 +            v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
 +            uint32_t length = array->Length();
 +            for (uint32_t ii = 0; ii < length; ++ii) 
 +                qlistPtr->append(engine->toQObject(array->Get(ii)));
 +        } else {
 +            qlistPtr->append(engine->toQObject(value));
 +        }
 +        type = callType;
 +    } else if (callType == qMetaTypeId<QQmlV8Handle>()) {
 +        handlePtr = new (&allocData) QQmlV8Handle(QQmlV8Handle::fromHandle(value));
 +        type = callType;
 +    } else {
 +        qvariantPtr = new (&allocData) QVariant();
 +        type = -1;
 +
 +        QQmlEnginePrivate *ep = engine->engine() ? QQmlEnginePrivate::get(engine->engine()) : 0;
 +        QVariant v = engine->toVariant(value, -1);
 +
 +        if (v.userType() == callType) {
 +            *qvariantPtr = v;
 +        } else if (v.canConvert((QVariant::Type)callType)) {
 +            *qvariantPtr = v;
 +            qvariantPtr->convert((QVariant::Type)callType);
 +        } else if (const QMetaObject *mo = ep ? ep->rawMetaObjectForType(callType) : 0) {
 +            QObject *obj = ep->toQObject(v);
 +            
 +            if (obj) {
 +                const QMetaObject *objMo = obj->metaObject();
 +                while (objMo && objMo != mo) objMo = objMo->superClass();
 +                if (!objMo) obj = 0;
 +            }
 +
 +            *qvariantPtr = QVariant(callType, &obj);
 +        } else {
 +            *qvariantPtr = QVariant(callType, (void *)0);
 +        }
 +    }
 +}
 +
 +v8::Handle<v8::Value> CallArgument::toValue(QV8Engine *engine)
 +{
 +    if (type == qMetaTypeId<QJSValue>()) {
 +        return QJSValuePrivate::get(*qjsValuePtr)->asV8Value(engine);
 +    } else if (type == QMetaType::Int) {
 +        return v8::Integer::New(int(intValue));
 +    } else if (type == QMetaType::UInt) {
 +        return v8::Integer::NewFromUnsigned(intValue);
 +    } else if (type == QMetaType::Bool) {
 +        return v8::Boolean::New(boolValue);
 +    } else if (type == QMetaType::Double) {
 +        return v8::Number::New(doubleValue);
 +    } else if (type == QMetaType::Float) {
 +        return v8::Number::New(floatValue);
 +    } else if (type == QMetaType::QString) {
 +        return engine->toString(*qstringPtr);
 +    } else if (type == QMetaType::QObjectStar) {
 +        QObject *object = qobjectPtr;
 +        if (object)
 +            QQmlData::get(object, true)->setImplicitDestructible();
 +        return engine->newQObject(object);
 +    } else if (type == qMetaTypeId<QList<QObject *> >()) {
 +        // XXX Can this be made more by using Array as a prototype and implementing
 +        // directly against QList<QObject*>?
 +        QList<QObject *> &list = *qlistPtr;
 +        v8::Local<v8::Array> array = v8::Array::New(list.count());
 +        for (int ii = 0; ii < list.count(); ++ii) 
 +            array->Set(ii, engine->newQObject(list.at(ii)));
 +        return array;
 +    } else if (type == qMetaTypeId<QQmlV8Handle>()) {
 +        return handlePtr->toHandle();
 +    } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
 +        QVariant value = *qvariantPtr;
 +        v8::Handle<v8::Value> rv = engine->fromVariant(value);
 +        if (QObject *object = engine->toQObject(rv)) 
 +            QQmlData::get(object, true)->setImplicitDestructible();
 +        return rv;
 +    } else {
 +        return v8::Undefined();
 +    }
 +}
 +
 +QT_END_NAMESPACE
 +
Simple merge
index 0000000,ef79d05..618178f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,613 +1,613 @@@
 -** This file is part of the Declarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
 -#include <QtDeclarative/qdeclarativeinfo.h>
++** This file is part of the QtQuick module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #include "qquickanimatedsprite_p.h"
+ #include "qquicksprite_p.h"
+ #include "qquickspriteengine_p.h"
+ #include <QtQuick/private/qsgcontext_p.h>
+ #include <private/qsgadaptationlayer_p.h>
+ #include <QtQuick/qsgnode.h>
+ #include <QtQuick/qsgengine.h>
+ #include <QtQuick/qsgtexturematerial.h>
+ #include <QtQuick/qsgtexture.h>
+ #include <QtQuick/qquickcanvas.h>
 -    } else if (m_spriteEngine->status() == QDeclarativePixmap::Null) {
++#include <QtQml/qqmlinfo.h>
+ #include <QFile>
+ #include <cmath>
+ #include <qmath.h>
+ #include <QDebug>
+ QT_BEGIN_NAMESPACE
+ static const char vertexShaderCode[] =
+     "attribute highp vec2 vTex;\n"
+     "uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress\n"
+     "uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation)\n"
+     "uniform highp vec2 size;//w,h of element\n"
+     "\n"
+     "uniform highp mat4 qt_Matrix;\n"
+     "\n"
+     "varying highp vec4 fTexS;\n"
+     "varying lowp float progress;\n"
+     "\n"
+     "\n"
+     "void main() {\n"
+     "    progress = animData.z;\n"
+     "    //Calculate frame location in texture\n"
+     "    fTexS.xy = animPos.xy + vTex.xy * animData.xy;\n"
+     "    //Next frame is also passed, for interpolation\n"
+     "    fTexS.zw = animPos.zw + vTex.xy * animData.xy;\n"
+     "\n"
+     "    gl_Position = qt_Matrix * vec4(size.x * vTex.x, size.y * vTex.y, 0, 1);\n"
+     "}\n";
+ static const char fragmentShaderCode[] =
+     "uniform sampler2D texture;\n"
+     "uniform lowp float qt_Opacity;\n"
+     "\n"
+     "varying highp vec4 fTexS;\n"
+     "varying lowp float progress;\n"
+     "\n"
+     "void main() {\n"
+     "    gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), progress) * qt_Opacity;\n"
+     "}\n";
+ class QQuickAnimatedSpriteMaterial : public QSGMaterial
+ {
+ public:
+     QQuickAnimatedSpriteMaterial();
+     ~QQuickAnimatedSpriteMaterial();
+     virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
+     virtual QSGMaterialShader *createShader() const;
+     virtual int compare(const QSGMaterial *other) const
+     {
+         return this - static_cast<const QQuickAnimatedSpriteMaterial *>(other);
+     }
+     QSGTexture *texture;
+     float animT;
+     float animX1;
+     float animY1;
+     float animX2;
+     float animY2;
+     float animW;
+     float animH;
+     float elementWidth;
+     float elementHeight;
+ };
+ QQuickAnimatedSpriteMaterial::QQuickAnimatedSpriteMaterial()
+     : texture(0)
+     , animT(0.0f)
+     , animX1(0.0f)
+     , animY1(0.0f)
+     , animX2(0.0f)
+     , animY2(0.0f)
+     , animW(1.0f)
+     , animH(1.0f)
+     , elementWidth(1.0f)
+     , elementHeight(1.0f)
+ {
+     setFlag(Blending, true);
+ }
+ QQuickAnimatedSpriteMaterial::~QQuickAnimatedSpriteMaterial()
+ {
+     delete texture;
+ }
+ class AnimatedSpriteMaterialData : public QSGMaterialShader
+ {
+ public:
+     AnimatedSpriteMaterialData(const char * /* vertexFile */ = 0, const char * /* fragmentFile */ = 0)
+     {
+     }
+     void deactivate() {
+         QSGMaterialShader::deactivate();
+         for (int i=0; i<8; ++i) {
+             program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
+         }
+     }
+     virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
+     {
+         QQuickAnimatedSpriteMaterial *m = static_cast<QQuickAnimatedSpriteMaterial *>(newEffect);
+         m->texture->bind();
+         program()->setUniformValue(m_opacity_id, state.opacity());
+         program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT);
+         program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2);
+         program()->setUniformValue(m_size_id, m->elementWidth, m->elementHeight);
+         if (state.isMatrixDirty())
+             program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+     }
+     virtual void initialize() {
+         m_matrix_id = program()->uniformLocation("qt_Matrix");
+         m_opacity_id = program()->uniformLocation("qt_Opacity");
+         m_animData_id = program()->uniformLocation("animData");
+         m_animPos_id = program()->uniformLocation("animPos");
+         m_size_id = program()->uniformLocation("size");
+     }
+     virtual const char *vertexShader() const { return vertexShaderCode; }
+     virtual const char *fragmentShader() const { return fragmentShaderCode; }
+     virtual char const *const *attributeNames() const {
+         static const char *attr[] = {
+            "vTex",
+             0
+         };
+         return attr;
+     }
+     int m_matrix_id;
+     int m_opacity_id;
+     int m_animData_id;
+     int m_animPos_id;
+     int m_size_id;
+     static float chunkOfBytes[1024];
+ };
+ float AnimatedSpriteMaterialData::chunkOfBytes[1024];
+ QSGMaterialShader *QQuickAnimatedSpriteMaterial::createShader() const
+ {
+     return new AnimatedSpriteMaterialData;
+ }
+ struct AnimatedSpriteVertex {
+     float tx;
+     float ty;
+ };
+ struct AnimatedSpriteVertices {
+     AnimatedSpriteVertex v1;
+     AnimatedSpriteVertex v2;
+     AnimatedSpriteVertex v3;
+     AnimatedSpriteVertex v4;
+ };
+ /*!
+     \qmlclass AnimatedSprite QQuickAnimatedSprite
+     \inqmlmodule QtQuick 2
+     \inherits Item
+     \brief The AnimatedSprite element draws a sprite animation
+ */
+ /*!
+     \qmlproperty bool QtQuick2::AnimatedSprite::running
+     Whether the sprite is animating or not.
+     Default is true
+ */
+ /*!
+     \qmlproperty bool QtQuick2::AnimatedSprite::interpolate
+     If true, interpolation will occur between sprite frames to make the
+     animation appear smoother.
+     Default is true.
+ */
+ /*!
+     \qmlproperty qreal QtQuick2::AnimatedSprite::frameRate
+     Frames per second to show in the animation. Values below 0 are invalid.
+     If frameRate is valid  then it will be used to calculate the duration of the frames.
+     If not, and frameDuration is valid , then frameDuration will be used.
+ */
+ /*!
+     \qmlproperty int QtQuick2::AnimatedSprite::frameDuration
+     Duration of each frame of the animation. Values below 0 are invalid.
+     If frameRate is valid then it will be used to calculate the duration of the frames.
+     If not, and frameDuration is valid, then frameDuration will be used.
+ */
+ /*!
+     \qmlproperty int QtQuick2::AnimatedSprite::frameCount
+     Number of frames in this AnimatedSprite.
+ */
+ /*!
+     \qmlproperty int QtQuick2::AnimatedSprite::frameHeight
+     Height of a single frame in this AnimatedSprite.
+     May be omitted if it is the only sprite in the file.
+ */
+ /*!
+     \qmlproperty int QtQuick2::AnimatedSprite::frameWidth
+     Width of a single frame in this AnimatedSprite.
+     May be omitted if it is the only sprite in the file.
+ */
+ /*!
+     \qmlproperty int QtQuick2::AnimatedSprite::frameX
+     The X coordinate in the image file of the first frame of the AnimatedSprite.
+     May be omitted if the first frame starts in the upper left corner of the file.
+ */
+ /*!
+     \qmlproperty int QtQuick2::AnimatedSprite::frameY
+     The Y coordinate in the image file of the first frame of the AnimatedSprite.
+     May be omitted if the first frame starts in the upper left corner of the file.
+ */
+ /*!
+     \qmlproperty url QtQuick2::AnimatedSprite::source
+     The image source for the animation.
+     If frameHeight and frameWidth are not specified, it is assumed to be a single long row of square frames.
+     Otherwise, it can be multiple contiguous rows or rectangluar frames, when one row runs out the next will be used.
+     If frameX and frameY are specified, the row of frames will be taken with that x/y coordinate as the upper left corner.
+ */
+ /*!
+     \qmlproperty bool QtQuick2::AnimatedSprite::reverse
+     If true, then the animation will be played in reverse.
+     Default is false.
+ */
+ /*!
+     \qmlproperty bool QtQuick2::AnimatedSprite::frameSync
+     If true, then the animation will have no duration. Instead, the animation will advance
+     one frame each time a frame is rendered to the screen. This syncronizes it with the painting
+     rate as opposed to elapsed time.
+     If frameSync is set to true, it overrides both frameRate and frameDuration.
+     Default is false.
+ */
+ /*!
+     \qmlproperty int QtQuick2::AnimatedSprite::loops
+     After playing the animation this many times, the animation will automatically stop. Negative values are invalid.
+     If this is set to AnimatedSprite.Infinite the animation will not stop playing on its own.
+     Default is AnimatedSprite.Infinite
+ */
+ /*!
+     \qmlproperty bool QtQuick2::AnimatedSprite::paused
+     When paused, the current frame can be advanced manually.
+     Default is false.
+ */
+ /*!
+     \qmlproperty int QtQuick2::AnimatedSprite::currentFrame
+     When paused, the current frame can be advanced manually by setting this property or calling advance().
+ */
+ //TODO: Implicitly size element to size of sprite
+ QQuickAnimatedSprite::QQuickAnimatedSprite(QQuickItem *parent) :
+     QQuickItem(parent)
+     , m_node(0)
+     , m_material(0)
+     , m_sprite(new QQuickSprite)
+     , m_spriteEngine(0)
+     , m_curFrame(0)
+     , m_pleaseReset(false)
+     , m_running(true)
+     , m_paused(false)
+     , m_interpolate(true)
+     , m_loops(-1)
+     , m_curLoop(0)
+     , m_pauseOffset(0)
+ {
+     setFlag(ItemHasContents);
+     connect(this, SIGNAL(runningChanged(bool)),
+             this, SLOT(update()));
+ }
+ void QQuickAnimatedSprite::reloadImage()
+ {
+     if (!isComponentComplete())
+         return;
+     createEngine();//### It's not as inefficient as it sounds, but it still sucks having to recreate the engine
+ }
+ void QQuickAnimatedSprite::componentComplete()
+ {
+     createEngine();
+     QQuickItem::componentComplete();
+     if (m_running)
+         start();
+ }
+ void QQuickAnimatedSprite::start()
+ {
+     if (m_running)
+         return;
+     m_curLoop = 0;
+     m_timestamp.start();
+     m_running = true;
+     emit runningChanged(true);
+     update();
+ }
+ void QQuickAnimatedSprite::stop()
+ {
+     if (!m_running)
+         return;
+     m_running = false;
+     emit runningChanged(false);
+ }
+ void QQuickAnimatedSprite::advance(int frames)
+ {
+     if (!frames)
+         return;
+     //TODO-C: May not work when running - only when paused
+     m_curFrame += frames;
+     while (m_curFrame < 0)
+         m_curFrame += m_sprite->frames();
+     m_curFrame = m_curFrame % m_sprite->frames();
+     emit currentFrameChanged(m_curFrame);
+ }
+ void QQuickAnimatedSprite::pause()
+ {
+     if (m_paused)
+         return;
+     m_pauseOffset = m_timestamp.elapsed();
+     m_paused = true;
+     emit pausedChanged(true);
+ }
+ void QQuickAnimatedSprite::resume()
+ {
+     if (!m_paused)
+         return;
+     m_pauseOffset = m_pauseOffset - m_timestamp.elapsed();
+     m_paused = false;
+     emit pausedChanged(false);
+ }
+ void QQuickAnimatedSprite::createEngine()
+ {
+     if (m_spriteEngine)
+         delete m_spriteEngine;
+     QList<QQuickSprite*> spriteList;
+     spriteList << m_sprite;
+     m_spriteEngine = new QQuickSpriteEngine(QList<QQuickSprite*>(spriteList), this);
+     m_spriteEngine->startAssemblingImage();
+     reset();
+ }
+ static QSGGeometry::Attribute AnimatedSprite_Attributes[] = {
+     QSGGeometry::Attribute::create(0, 2, GL_FLOAT),         // tex
+ };
+ static QSGGeometry::AttributeSet AnimatedSprite_AttributeSet =
+ {
+     1, // Attribute Count
+     2 * sizeof(float),
+     AnimatedSprite_Attributes
+ };
+ QSGGeometryNode* QQuickAnimatedSprite::buildNode()
+ {
+     if (!m_spriteEngine) {
+         qmlInfo(this) << "No sprite engine...";
+         return 0;
 -    } else if (m_spriteEngine->status() == QDeclarativePixmap::Loading) {
++    } else if (m_spriteEngine->status() == QQuickPixmap::Null) {
+         m_spriteEngine->startAssemblingImage();
+         update();//Schedule another update, where we will check again
+         return 0;
++    } else if (m_spriteEngine->status() == QQuickPixmap::Loading) {
+         update();//Schedule another update, where we will check again
+         return 0;
+     }
+     m_material = new QQuickAnimatedSpriteMaterial();
+     QImage image = m_spriteEngine->assembledImage();
+     if (image.isNull())
+         return 0;
+     m_sheetSize = QSizeF(image.size());
+     m_material->texture = canvas()->createTextureFromImage(image);
+     m_material->texture->setFiltering(QSGTexture::Linear);
+     m_spriteEngine->start(0);
+     m_material->animT = 0;
+     m_material->animX1 = m_spriteEngine->spriteX() / m_sheetSize.width();
+     m_material->animY1 = m_spriteEngine->spriteY() / m_sheetSize.height();
+     m_material->animX2 = m_material->animX1;
+     m_material->animY2 = m_material->animY1;
+     m_material->animW = m_spriteEngine->spriteWidth() / m_sheetSize.width();
+     m_material->animH = m_spriteEngine->spriteHeight() / m_sheetSize.height();
+     m_material->elementWidth = width();
+     m_material->elementHeight = height();
+     int vCount = 4;
+     int iCount = 6;
+     QSGGeometry *g = new QSGGeometry(AnimatedSprite_AttributeSet, vCount, iCount);
+     g->setDrawingMode(GL_TRIANGLES);
+     AnimatedSpriteVertices *p = (AnimatedSpriteVertices *) g->vertexData();
+     p->v1.tx = 0;
+     p->v1.ty = 0;
+     p->v2.tx = 1.0;
+     p->v2.ty = 0;
+     p->v3.tx = 0;
+     p->v3.ty = 1.0;
+     p->v4.tx = 1.0;
+     p->v4.ty = 1.0;
+     quint16 *indices = g->indexDataAsUShort();
+     indices[0] = 0;
+     indices[1] = 1;
+     indices[2] = 2;
+     indices[3] = 1;
+     indices[4] = 3;
+     indices[5] = 2;
+     m_timestamp.start();
+     m_node = new QSGGeometryNode();
+     m_node->setGeometry(g);
+     m_node->setMaterial(m_material);
+     m_node->setFlag(QSGGeometryNode::OwnsMaterial);
+     return m_node;
+ }
+ void QQuickAnimatedSprite::reset()
+ {
+     m_pleaseReset = true;
+ }
+ QSGNode *QQuickAnimatedSprite::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
+ {
+     if (m_pleaseReset) {
+         delete m_node;
+         m_node = 0;
+         m_material = 0;
+         m_pleaseReset = false;
+     }
+     prepareNextFrame();
+     if (m_running) {
+         update();
+         if (m_node)
+             m_node->markDirty(QSGNode::DirtyMaterial);
+     }
+     return m_node;
+ }
+ void QQuickAnimatedSprite::prepareNextFrame()
+ {
+     if (m_node == 0)
+         m_node = buildNode();
+     if (m_node == 0) //error creating node
+         return;
+     uint timeInt = m_timestamp.elapsed() + m_pauseOffset;
+     qreal time =  timeInt / 1000.;
+     m_material->elementHeight = height();
+     m_material->elementWidth = width();
+     double frameAt; //double just for modf
+     qreal progress;
+     if (!m_paused) {
+         //Advance State (keeps time for psuedostates)
+         m_spriteEngine->updateSprites(timeInt);
+         //Advance AnimatedSprite
+         qreal animT = m_spriteEngine->spriteStart()/1000.0;
+         qreal frameCount = m_spriteEngine->spriteFrames();
+         qreal frameDuration = m_spriteEngine->spriteDuration()/frameCount;
+         if (frameDuration > 0) {
+             qreal frame = (time - animT)/(frameDuration / 1000.0);
+             frame = qBound(qreal(0.0), frame, frameCount - qreal(1.0));//Stop at count-1 frames until we have between anim interpolation
+             progress = modf(frame,&frameAt);
+             if (m_curFrame > frameAt) //went around
+                 m_curLoop++;
+             m_curFrame = frameAt;
+         } else {
+             m_curFrame++;
+             if (m_curFrame >= frameCount){
+                 m_curFrame = 0;
+                 m_curLoop++;
+                 m_spriteEngine->advance();
+             }
+             frameAt = m_curFrame;
+             progress = 0;
+         }
+         if (m_loops > 0 && m_curLoop >= m_loops) {
+             frameAt = 0;
+             m_running = false;
+         }
+     } else {
+         frameAt = m_curFrame;
+     }
+     if (m_spriteEngine->sprite()->reverse())
+         frameAt = (m_spriteEngine->spriteFrames() - 1) - frameAt;
+     qreal y = m_spriteEngine->spriteY() / m_sheetSize.height();
+     qreal w = m_spriteEngine->spriteWidth() / m_sheetSize.width();
+     qreal h = m_spriteEngine->spriteHeight() / m_sheetSize.height();
+     qreal x1 = m_spriteEngine->spriteX() / m_sheetSize.width();
+     x1 += frameAt * w;
+     qreal x2 = x1;
+     if (frameAt < (m_spriteEngine->spriteFrames()-1))
+         x2 += w;
+     m_material->animX1 = x1;
+     m_material->animY1 = y;
+     m_material->animX2 = x2;
+     m_material->animY2 = y;
+     m_material->animW = w;
+     m_material->animH = h;
+     m_material->animT = m_interpolate ? progress : 0.0;
+ }
+ QT_END_NAMESPACE
index 0000000,062b191..708f94b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,373 +1,373 @@@
 -** This file is part of the Declarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
++** This file is part of the QtQuick module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #ifndef QQUICKANIMATEDSPRITE_P_H
+ #define QQUICKANIMATEDSPRITE_P_H
+ #include <QtQuick/QQuickItem>
+ #include <private/qquicksprite_p.h>
+ #include <QTime>
+ QT_BEGIN_HEADER
+ QT_BEGIN_NAMESPACE
+ class QSGContext;
+ class QQuickSprite;
+ class QQuickSpriteEngine;
+ class QSGGeometryNode;
+ class QQuickAnimatedSpriteMaterial;
+ class Q_AUTOTEST_EXPORT QQuickAnimatedSprite : public QQuickItem
+ {
+     Q_OBJECT
+     Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
+     Q_PROPERTY(bool interpolate READ interpolate WRITE setInterpolate NOTIFY interpolateChanged)
+     //###try to share similar spriteEngines for less overhead?
+     //These properties come out of QQuickSprite, since a SimpleSpriteImage is a renderer for a single sprite
+     Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+     Q_PROPERTY(bool reverse READ reverse WRITE setReverse NOTIFY reverseChanged)
+     Q_PROPERTY(bool frameSync READ frameSync WRITE setFrameSync NOTIFY frameSyncChanged)
+     Q_PROPERTY(int frameCount READ frameCount WRITE setFrameCount NOTIFY frameCountChanged)
+     //If frame height or width is not specified, it is assumed to be a single long row of square frames.
+     //Otherwise, it can be multiple contiguous rows, when one row runs out the next will be used.
+     Q_PROPERTY(int frameHeight READ frameHeight WRITE setFrameHeight NOTIFY frameHeightChanged)
+     Q_PROPERTY(int frameWidth READ frameWidth WRITE setFrameWidth NOTIFY frameWidthChanged)
+     Q_PROPERTY(int frameX READ frameX WRITE setFrameX NOTIFY frameXChanged)
+     Q_PROPERTY(int frameY READ frameY WRITE setFrameY NOTIFY frameYChanged)
+     //Precedence order: frameRate, frameDuration
+     Q_PROPERTY(qreal frameRate READ frameRate WRITE setFrameRate NOTIFY frameRateChanged RESET resetFrameRate)
+     Q_PROPERTY(int frameDuration READ frameDuration WRITE setFrameDuration NOTIFY frameDurationChanged RESET resetFrameDuration)
+     //Extra Simple Sprite Stuff
+     Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged)
+     Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged)
+     Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged)
+     Q_ENUMS(LoopParameters)
+ public:
+     explicit QQuickAnimatedSprite(QQuickItem *parent = 0);
+     enum LoopParameters {
+         Infinite = -1
+     };
+     bool running() const
+     {
+         return m_running;
+     }
+     bool interpolate() const
+     {
+         return m_interpolate;
+     }
+     QUrl source() const
+     {
+         return m_sprite->source();
+     }
+     bool reverse() const
+     {
+         return m_sprite->reverse();
+     }
+     bool frameSync() const
+     {
+         return m_sprite->frameSync();
+     }
+     int frameCount() const
+     {
+         return m_sprite->frames();
+     }
+     int frameHeight() const
+     {
+         return m_sprite->frameHeight();
+     }
+     int frameWidth() const
+     {
+         return m_sprite->frameWidth();
+     }
+     int frameX() const
+     {
+         return m_sprite->frameX();
+     }
+     int frameY() const
+     {
+         return m_sprite->frameY();
+     }
+     qreal frameRate() const
+     {
+         return m_sprite->frameRate();
+     }
+     int frameDuration() const
+     {
+         return m_sprite->frameDuration();
+     }
+     int loops() const
+     {
+         return m_loops;
+     }
+     bool paused() const
+     {
+         return m_paused;
+     }
+     int currentFrame() const
+     {
+         return m_curFrame;
+     }
+ signals:
+     void pausedChanged(bool arg);
+     void runningChanged(bool arg);
+     void interpolateChanged(bool arg);
+     void sourceChanged(QUrl arg);
+     void reverseChanged(bool arg);
+     void frameSyncChanged(bool arg);
+     void frameCountChanged(int arg);
+     void frameHeightChanged(int arg);
+     void frameWidthChanged(int arg);
+     void frameXChanged(int arg);
+     void frameYChanged(int arg);
+     void frameRateChanged(qreal arg);
+     void frameDurationChanged(int arg);
+     void loopsChanged(int arg);
+     void currentFrameChanged(int arg);
+ public slots:
+     void start();
+     void stop();
+     void restart() {stop(); start();}
+     void advance(int frames=1);
+     void pause();
+     void resume();
+     void setRunning(bool arg)
+     {
+         if (m_running != arg) {
+             if (m_running)
+                 stop();
+             else
+                 start();
+         }
+     }
+     void setPaused(bool arg)
+     {
+         if (m_paused != arg) {
+             if (m_paused)
+                 resume();
+             else
+                 pause();
+         }
+     }
+     void setInterpolate(bool arg)
+     {
+         if (m_interpolate != arg) {
+             m_interpolate = arg;
+             emit interpolateChanged(arg);
+         }
+     }
+     void setSource(QUrl arg)
+     {
+         if (m_sprite->m_source != arg) {
+             m_sprite->setSource(arg);
+             emit sourceChanged(arg);
+         }
+     }
+     void setReverse(bool arg)
+     {
+         if (m_sprite->m_reverse != arg) {
+             m_sprite->setReverse(arg);
+             emit reverseChanged(arg);
+         }
+     }
+     void setFrameSync(bool arg)
+     {
+         if (m_sprite->m_frameSync != arg) {
+             m_sprite->setFrameSync(arg);
+             emit frameSyncChanged(arg);
+         }
+     }
+     void setFrameCount(int arg)
+     {
+         if (m_sprite->m_frames != arg) {
+             m_sprite->setFrameCount(arg);
+             emit frameCountChanged(arg);
+             reloadImage();
+         }
+     }
+     void setFrameHeight(int arg)
+     {
+         if (m_sprite->m_frameHeight != arg) {
+             m_sprite->setFrameHeight(arg);
+             emit frameHeightChanged(arg);
+             reloadImage();
+         }
+     }
+     void setFrameWidth(int arg)
+     {
+         if (m_sprite->m_frameWidth != arg) {
+             m_sprite->setFrameWidth(arg);
+             emit frameWidthChanged(arg);
+             reloadImage();
+         }
+     }
+     void setFrameX(int arg)
+     {
+         if (m_sprite->m_frameX != arg) {
+             m_sprite->setFrameX(arg);
+             emit frameXChanged(arg);
+             reloadImage();
+         }
+     }
+     void setFrameY(int arg)
+     {
+         if (m_sprite->m_frameY != arg) {
+             m_sprite->setFrameY(arg);
+             emit frameYChanged(arg);
+             reloadImage();
+         }
+     }
+     void setFrameRate(qreal arg)
+     {
+         if (m_sprite->m_frameRate != arg) {
+             m_sprite->setFrameRate(arg);
+             emit frameRateChanged(arg);
+         }
+     }
+     void setFrameDuration(int arg)
+     {
+         if (m_sprite->m_frameDuration != arg) {
+             m_sprite->setFrameDuration(arg);
+             emit frameDurationChanged(arg);
+         }
+     }
+     void resetFrameRate()
+     {
+         setFrameRate(-1.0);
+     }
+     void resetFrameDuration()
+     {
+         setFrameDuration(-1);
+     }
+     void setLoops(int arg)
+     {
+         if (m_loops != arg) {
+             m_loops = arg;
+             emit loopsChanged(arg);
+         }
+     }
+     void setCurrentFrame(int arg) //TODO-C: Probably only works when paused
+     {
+         if (m_curFrame != arg) {
+             m_curFrame = arg;
+             emit currentFrameChanged(arg); //TODO-C Only emitted on manual advance!
+         }
+     }
+ private slots:
+     void createEngine();
+ protected:
+     void reset();
+     void componentComplete();
+     QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ private:
+     void prepareNextFrame();
+     void reloadImage();
+     QSGGeometryNode* buildNode();
+     QSGGeometryNode *m_node;
+     QQuickAnimatedSpriteMaterial *m_material;
+     QQuickSprite* m_sprite;
+     QQuickSpriteEngine* m_spriteEngine;
+     QTime m_timestamp;
+     int m_curFrame;
+     bool m_pleaseReset;
+     bool m_running;
+     bool m_paused;
+     bool m_interpolate;
+     QSizeF m_sheetSize;
+     int m_loops;
+     int m_curLoop;
+     int m_pauseOffset;
+ };
+ QT_END_NAMESPACE
+ QT_END_HEADER
+ #endif // QQUICKANIMATEDSPRITE_P_H
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1627,7 -1626,7 +1627,7 @@@ void QQuickItemPrivate::setAccessibleFl
  
      \inmodule QtQuick
  
--    All visual items in Qt Declarative inherit from QQuickItem.  Although QQuickItem
++    All visual items in Qt Quick inherit from QQuickItem.  Although QQuickItem
      has no visual appearance, it defines all the properties that are
      common across visual items - such as the x and y position, the
      width and height, \l {anchor-layout}{anchoring} and key handling.
      \ingroup qml-basic-visual-elements
      \brief The Item is the most basic of all visual items in QML.
  
--    All visual items in Qt Declarative inherit from Item.  Although Item
++    All visual items in Qt Quick inherit from Item.  Although Item
      has no visual appearance, it defines all the properties that are
      common across visual items - such as the x and y position, the
      width and height, \l {anchor-layout}{anchoring} and key handling.
Simple merge
index 1316a3d,0000000..32f1047
mode 100644,000000..100644
--- /dev/null
@@@ -1,1042 -1,0 +1,1044 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qquickitemanimation_p.h"
 +#include "qquickitemanimation_p_p.h"
 +#include "qquickstateoperations_p.h"
 +
 +#include <private/qqmlproperty_p.h>
 +#include <private/qquickpath_p.h>
 +
 +#include <QtQml/qqmlinfo.h>
 +#include <QtCore/qmath.h>
 +#include "private/qsequentialanimationgroupjob_p.h"
 +#include "private/qparallelanimationgroupjob_p.h"
 +#include <QtGui/qtransform.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +/*!
 +    \qmlclass ParentAnimation QQuickParentAnimation
 +    \inqmlmodule QtQuick 2
 +    \ingroup qml-animation-transition
 +    \since QtQuick 2.0
 +    \inherits Animation
 +    \brief The ParentAnimation element animates changes in parent values.
 +
 +    ParentAnimation is used to animate a parent change for an \l Item.
 +
 +    For example, the following ParentChange changes \c blueRect to become
 +    a child of \c redRect when it is clicked. The inclusion of the
 +    ParentAnimation, which defines a NumberAnimation to be applied during
 +    the transition, ensures the item animates smoothly as it moves to
 +    its new parent:
 +
 +    \snippet doc/src/snippets/qml/parentanimation.qml 0
 +
 +    A ParentAnimation can contain any number of animations. These animations will
 +    be run in parallel; to run them sequentially, define them within a
 +    SequentialAnimation.
 +
 +    In some cases, such as when reparenting between items with clipping enabled, it is useful
 +    to animate the parent change via another item that does not have clipping
 +    enabled. Such an item can be set using the \l via property.
 +
 +    For convenience, when a ParentAnimation is used in a \l Transition, it will
 +    animate any ParentChange that has occurred during the state change.
 +    This can be overridden by setting a specific target item using the
 +    \l target property.
 +
 +    Like any other animation element, a ParentAnimation can be applied in a
 +    number of ways, including transitions, behaviors and property value
 +    sources. The \l {QML Animation and Transitions} documentation shows a
 +    variety of methods for creating animations.
 +
 +    \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example}
 +*/
 +QQuickParentAnimation::QQuickParentAnimation(QObject *parent)
 +    : QQuickAnimationGroup(*(new QQuickParentAnimationPrivate), parent)
 +{
 +}
 +
 +QQuickParentAnimation::~QQuickParentAnimation()
 +{
 +}
 +
 +/*!
 +    \qmlproperty Item QtQuick2::ParentAnimation::target
 +    The item to reparent.
 +
 +    When used in a transition, if no target is specified, all
 +    ParentChange occurrences are animated by the ParentAnimation.
 +*/
 +QQuickItem *QQuickParentAnimation::target() const
 +{
 +    Q_D(const QQuickParentAnimation);
 +    return d->target;
 +}
 +
 +void QQuickParentAnimation::setTargetObject(QQuickItem *target)
 +{
 +    Q_D(QQuickParentAnimation);
 +    if (target == d->target)
 +        return;
 +
 +    d->target = target;
 +    emit targetChanged();
 +}
 +
 +/*!
 +    \qmlproperty Item QtQuick2::ParentAnimation::newParent
 +    The new parent to animate to.
 +
 +    If the ParentAnimation is defined within a \l Transition or \l Behavior,
 +    this value defaults to the value defined in the end state of the
 +    \l Transition, or the value of the property change that triggered the
 +    \l Behavior.
 +*/
 +QQuickItem *QQuickParentAnimation::newParent() const
 +{
 +    Q_D(const QQuickParentAnimation);
 +    return d->newParent;
 +}
 +
 +void QQuickParentAnimation::setNewParent(QQuickItem *newParent)
 +{
 +    Q_D(QQuickParentAnimation);
 +    if (newParent == d->newParent)
 +        return;
 +
 +    d->newParent = newParent;
 +    emit newParentChanged();
 +}
 +
 +/*!
 +    \qmlproperty Item QtQuick2::ParentAnimation::via
 +    The item to reparent via. This provides a way to do an unclipped animation
 +    when both the old parent and new parent are clipped.
 +
 +    \qml
 +    ParentAnimation {
 +        target: myItem
 +        via: topLevelItem
 +        // ...
 +    }
 +    \endqml
 +*/
 +QQuickItem *QQuickParentAnimation::via() const
 +{
 +    Q_D(const QQuickParentAnimation);
 +    return d->via;
 +}
 +
 +void QQuickParentAnimation::setVia(QQuickItem *via)
 +{
 +    Q_D(QQuickParentAnimation);
 +    if (via == d->via)
 +        return;
 +
 +    d->via = via;
 +    emit viaChanged();
 +}
 +
 +//### mirrors same-named function in QQuickItem
 +QPointF QQuickParentAnimationPrivate::computeTransformOrigin(QQuickItem::TransformOrigin origin, qreal width, qreal height) const
 +{
 +    switch (origin) {
 +    default:
 +    case QQuickItem::TopLeft:
 +        return QPointF(0, 0);
 +    case QQuickItem::Top:
 +        return QPointF(width / 2., 0);
 +    case QQuickItem::TopRight:
 +        return QPointF(width, 0);
 +    case QQuickItem::Left:
 +        return QPointF(0, height / 2.);
 +    case QQuickItem::Center:
 +        return QPointF(width / 2., height / 2.);
 +    case QQuickItem::Right:
 +        return QPointF(width, height / 2.);
 +    case QQuickItem::BottomLeft:
 +        return QPointF(0, height);
 +    case QQuickItem::Bottom:
 +        return QPointF(width / 2., height);
 +    case QQuickItem::BottomRight:
 +        return QPointF(width, height);
 +    }
 +}
 +
 +QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &actions,
 +                        QQmlProperties &modified,
 +                        TransitionDirection direction,
 +                        QObject *defaultTarget)
 +{
 +    Q_D(QQuickParentAnimation);
 +
 +    struct QQuickParentAnimationData : public QAbstractAnimationAction
 +    {
 +        QQuickParentAnimationData() {}
 +        ~QQuickParentAnimationData() { qDeleteAll(pc); }
 +
 +        QQuickStateActions actions;
 +        //### reverse should probably apply on a per-action basis
 +        bool reverse;
 +        QList<QQuickParentChange *> pc;
 +        virtual void doAction()
 +        {
 +            for (int ii = 0; ii < actions.count(); ++ii) {
 +                const QQuickAction &action = actions.at(ii);
 +                if (reverse)
 +                    action.event->reverse();
 +                else
 +                    action.event->execute();
 +            }
 +        }
 +    };
 +
 +    QQuickParentAnimationData *data = new QQuickParentAnimationData;
 +    QQuickParentAnimationData *viaData = new QQuickParentAnimationData;
 +
 +    bool hasExplicit = false;
 +    if (d->target && d->newParent) {
 +        data->reverse = false;
 +        QQuickAction myAction;
 +        QQuickParentChange *pc = new QQuickParentChange;
 +        pc->setObject(d->target);
 +        pc->setParent(d->newParent);
 +        myAction.event = pc;
 +        data->pc << pc;
 +        data->actions << myAction;
 +        hasExplicit = true;
 +        if (d->via) {
 +            viaData->reverse = false;
 +            QQuickAction myVAction;
 +            QQuickParentChange *vpc = new QQuickParentChange;
 +            vpc->setObject(d->target);
 +            vpc->setParent(d->via);
 +            myVAction.event = vpc;
 +            viaData->pc << vpc;
 +            viaData->actions << myVAction;
 +        }
 +        //### once actions have concept of modified,
 +        //    loop to match appropriate ParentChanges and mark as modified
 +    }
 +
 +    if (!hasExplicit)
 +    for (int i = 0; i < actions.size(); ++i) {
 +        QQuickAction &action = actions[i];
 +        if (action.event && action.event->type() == QQuickActionEvent::ParentChange
 +            && (!d->target || static_cast<QQuickParentChange*>(action.event)->object() == d->target)) {
 +
 +            QQuickParentChange *pc = static_cast<QQuickParentChange*>(action.event);
 +            QQuickAction myAction = action;
 +            data->reverse = action.reverseEvent;
 +
 +            //### this logic differs from PropertyAnimation
 +            //    (probably a result of modified vs. done)
 +            if (d->newParent) {
 +                QQuickParentChange *epc = new QQuickParentChange;
 +                epc->setObject(static_cast<QQuickParentChange*>(action.event)->object());
 +                epc->setParent(d->newParent);
 +                myAction.event = epc;
 +                data->pc << epc;
 +                data->actions << myAction;
 +                pc = epc;
 +            } else {
 +                action.actionDone = true;
 +                data->actions << myAction;
 +            }
 +
 +            if (d->via) {
 +                viaData->reverse = false;
 +                QQuickAction myAction;
 +                QQuickParentChange *vpc = new QQuickParentChange;
 +                vpc->setObject(pc->object());
 +                vpc->setParent(d->via);
 +                myAction.event = vpc;
 +                viaData->pc << vpc;
 +                viaData->actions << myAction;
 +                QQuickAction dummyAction;
 +                QQuickAction &xAction = pc->xIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
 +                QQuickAction &yAction = pc->yIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
 +                QQuickAction &sAction = pc->scaleIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
 +                QQuickAction &rAction = pc->rotationIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
 +                QQuickItem *target = pc->object();
 +                QQuickItem *targetParent = action.reverseEvent ? pc->originalParent() : pc->parent();
 +
 +                //### this mirrors the logic in QQuickParentChange.
 +                bool ok;
 +                const QTransform &transform = targetParent->itemTransform(d->via, &ok);
 +                if (transform.type() >= QTransform::TxShear || !ok) {
 +                    qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under complex transform");
 +                    ok = false;
 +                }
 +
 +                qreal scale = 1;
 +                qreal rotation = 0;
 +                bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
 +                if (ok && !isRotate) {
 +                    if (transform.m11() == transform.m22())
 +                        scale = transform.m11();
 +                    else {
 +                        qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under non-uniform scale");
 +                        ok = false;
 +                    }
 +                } else if (ok && isRotate) {
 +                    if (transform.m11() == transform.m22())
 +                        scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
 +                    else {
 +                        qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under non-uniform scale");
 +                        ok = false;
 +                    }
 +
 +                    if (scale != 0)
 +                        rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
 +                    else {
 +                        qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under scale of 0");
 +                        ok = false;
 +                    }
 +                }
 +
 +                const QPointF &point = transform.map(QPointF(xAction.toValue.toReal(),yAction.toValue.toReal()));
 +                qreal x = point.x();
 +                qreal y = point.y();
 +                if (ok && target->transformOrigin() != QQuickItem::TopLeft) {
 +                    qreal w = target->width();
 +                    qreal h = target->height();
 +                    if (pc->widthIsSet() && i < actions.size() - 1)
 +                        w = actions[++i].toValue.toReal();
 +                    if (pc->heightIsSet() && i < actions.size() - 1)
 +                        h = actions[++i].toValue.toReal();
 +                    const QPointF &transformOrigin
 +                            = d->computeTransformOrigin(target->transformOrigin(), w,h);
 +                    qreal tempxt = transformOrigin.x();
 +                    qreal tempyt = transformOrigin.y();
 +                    QTransform t;
 +                    t.translate(-tempxt, -tempyt);
 +                    t.rotate(rotation);
 +                    t.scale(scale, scale);
 +                    t.translate(tempxt, tempyt);
 +                    const QPointF &offset = t.map(QPointF(0,0));
 +                    x += offset.x();
 +                    y += offset.y();
 +                }
 +
 +                if (ok) {
 +                    //qDebug() << x << y << rotation << scale;
 +                    xAction.toValue = x;
 +                    yAction.toValue = y;
 +                    sAction.toValue = sAction.toValue.toReal() * scale;
 +                    rAction.toValue = rAction.toValue.toReal() + rotation;
 +                }
 +            }
 +        }
 +    }
 +
 +    QSequentialAnimationGroupJob *topLevelGroup = new QSequentialAnimationGroupJob;
 +    QActionAnimation *viaAction = d->via ? new QActionAnimation : 0;
 +    QActionAnimation *targetAction = new QActionAnimation;
 +    //we'll assume the common case by far is to have children, and always create ag
 +    QParallelAnimationGroupJob *ag = new QParallelAnimationGroupJob;
 +
 +    if (data->actions.count()) {
 +        if (d->via)
 +            viaAction->setAnimAction(viaData);
 +        targetAction->setAnimAction(data);
 +
 +        //take care of any child animations
 +        bool valid = d->defaultProperty.isValid();
 +        QAbstractAnimationJob* anim;
 +        for (int ii = 0; ii < d->animations.count(); ++ii) {
 +            if (valid)
 +                d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
 +            anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget);
 +            ag->appendAnimation(anim);
 +        }
 +
 +        //TODO: simplify/clarify logic
 +        bool forwards = direction == QQuickAbstractAnimation::Forward;
 +        if (forwards) {
 +            topLevelGroup->appendAnimation(d->via ? viaAction : targetAction);
 +            topLevelGroup->appendAnimation(ag);
 +            if (d->via)
 +                topLevelGroup->appendAnimation(targetAction);
 +        } else {
 +            if (d->via)
 +                topLevelGroup->appendAnimation(targetAction);
 +            topLevelGroup->appendAnimation(ag);
 +            topLevelGroup->appendAnimation(d->via ? viaAction : targetAction);
 +        }
 +    } else {
 +        delete data;
 +        delete viaData;
 +    }
 +
 +    return initInstance(topLevelGroup);
 +}
 +
 +/*!
 +    \qmlclass AnchorAnimation QQuickAnchorAnimation
 +    \inqmlmodule QtQuick 2
 +    \ingroup qml-animation-transition
 +    \inherits Animation
 +    \brief The AnchorAnimation element animates changes in anchor values.
 +
 +    AnchorAnimation is used to animate an anchor change.
 +
 +    In the following snippet we animate the addition of a right anchor to a \l Rectangle:
 +
 +    \snippet doc/src/snippets/qml/anchoranimation.qml 0
 +
 +    For convenience, when an AnchorAnimation is used in a \l Transition, it will
 +    animate any AnchorChanges that have occurred during the state change.
 +    This can be overridden by setting a specific target item using the
 +    \l target property.
 +
 +    Like any other animation element, an AnchorAnimation can be applied in a
 +    number of ways, including transitions, behaviors and property value
 +    sources. The \l {QML Animation and Transitions} documentation shows a
 +    variety of methods for creating animations.
 +
 +    \sa {QML Animation and Transitions}, AnchorChanges
 +*/
 +QQuickAnchorAnimation::QQuickAnchorAnimation(QObject *parent)
 +: QQuickAbstractAnimation(*(new QQuickAnchorAnimationPrivate), parent)
 +{
 +}
 +
 +QQuickAnchorAnimation::~QQuickAnchorAnimation()
 +{
 +}
 +
 +/*!
 +    \qmlproperty list<Item> QtQuick2::AnchorAnimation::targets
 +    The items to reanchor.
 +
 +    If no targets are specified all AnchorChanges will be
 +    animated by the AnchorAnimation.
 +*/
 +QQmlListProperty<QQuickItem> QQuickAnchorAnimation::targets()
 +{
 +    Q_D(QQuickAnchorAnimation);
 +    return QQmlListProperty<QQuickItem>(this, d->targets);
 +}
 +
 +/*!
 +    \qmlproperty int QtQuick2::AnchorAnimation::duration
 +    This property holds the duration of the animation, in milliseconds.
 +
 +    The default value is 250.
 +*/
 +int QQuickAnchorAnimation::duration() const
 +{
 +    Q_D(const QQuickAnchorAnimation);
 +    return d->duration;
 +}
 +
 +void QQuickAnchorAnimation::setDuration(int duration)
 +{
 +    if (duration < 0) {
 +        qmlInfo(this) << tr("Cannot set a duration of < 0");
 +        return;
 +    }
 +
 +    Q_D(QQuickAnchorAnimation);
 +    if (d->duration == duration)
 +        return;
 +    d->duration = duration;
 +    emit durationChanged(duration);
 +}
 +
 +/*!
 +    \qmlproperty enumeration QtQuick2::AnchorAnimation::easing.type
 +    \qmlproperty real QtQuick2::AnchorAnimation::easing.amplitude
 +    \qmlproperty real QtQuick2::AnchorAnimation::easing.overshoot
 +    \qmlproperty real QtQuick2::AnchorAnimation::easing.period
 +    \brief the easing curve used for the animation.
 +
 +    To specify an easing curve you need to specify at least the type. For some curves you can also specify
 +    amplitude, period and/or overshoot. The default easing curve is
 +    Linear.
 +
 +    \qml
 +    AnchorAnimation { easing.type: Easing.InOutQuad }
 +    \endqml
 +
 +    See the \l{PropertyAnimation::easing.type} documentation for information
 +    about the different types of easing curves.
 +*/
 +QEasingCurve QQuickAnchorAnimation::easing() const
 +{
 +    Q_D(const QQuickAnchorAnimation);
 +    return d->easing;
 +}
 +
 +void QQuickAnchorAnimation::setEasing(const QEasingCurve &e)
 +{
 +    Q_D(QQuickAnchorAnimation);
 +    if (d->easing == e)
 +        return;
 +
 +    d->easing = e;
 +    emit easingChanged(e);
 +}
 +
 +QAbstractAnimationJob* QQuickAnchorAnimation::transition(QQuickStateActions &actions,
 +                        QQmlProperties &modified,
 +                        TransitionDirection direction,
 +                        QObject *defaultTarget)
 +{
 +    Q_UNUSED(modified);
 +    Q_UNUSED(defaultTarget);
 +    Q_D(QQuickAnchorAnimation);
 +    QQuickAnimationPropertyUpdater *data = new QQuickAnimationPropertyUpdater;
 +    data->interpolatorType = QMetaType::QReal;
 +    data->interpolator = d->interpolator;
 +    data->reverse = direction == Backward ? true : false;
 +    data->fromSourced = false;
 +    data->fromDefined = false;
 +
 +    for (int ii = 0; ii < actions.count(); ++ii) {
 +        QQuickAction &action = actions[ii];
 +        if (action.event && action.event->type() == QQuickActionEvent::AnchorChanges
 +            && (d->targets.isEmpty() || d->targets.contains(static_cast<QQuickAnchorChanges*>(action.event)->object()))) {
 +            data->actions << static_cast<QQuickAnchorChanges*>(action.event)->additionalActions();
 +        }
 +    }
 +
 +    QQuickBulkValueAnimator *animator = new QQuickBulkValueAnimator;
 +    if (data->actions.count()) {
 +        animator->setAnimValue(data);
 +        animator->setFromSourcedValue(&data->fromSourced);
 +    } else {
 +        delete data;
 +    }
 +
++    animator->setDuration(d->duration);
++    animator->setEasingCurve(d->easing);
 +    return initInstance(animator);
 +}
 +
 +/*!
 +    \qmlclass PathAnimation QQuickPathAnimation
 +    \inqmlmodule QtQuick 2
 +    \ingroup qml-animation-transition
 +    \inherits Animation
 +    \since QtQuick 2.0
 +    \brief The PathAnimation element animates an item along a path.
 +
 +    When used in a transition, the path can be specified without start
 +    or end points, for example:
 +    \qml
 +    PathAnimation {
 +        path: Path {
 +            //no startX, startY
 +            PathCurve { x: 100; y: 100}
 +            PathCurve {}    //last element is empty with no end point specified
 +        }
 +    }
 +    \endqml
 +
 +    In the above case, the path start will be the item's current position, and the
 +    path end will be the item's target position in the target state.
 +
 +    \sa {QML Animation and Transitions}, PathInterpolator
 +*/
 +QQuickPathAnimation::QQuickPathAnimation(QObject *parent)
 +: QQuickAbstractAnimation(*(new QQuickPathAnimationPrivate), parent)
 +{
 +}
 +
 +QQuickPathAnimation::~QQuickPathAnimation()
 +{
 +    Q_D(QQuickPathAnimation);
 +    QHash<QQuickItem*, QQuickPathAnimationAnimator* >::iterator it;
 +    for (it = d->activeAnimations.begin(); it != d->activeAnimations.end(); ++it) {
 +        it.value()->clearTemplate();
 +    }
 +}
 +
 +/*!
 +    \qmlproperty int QtQuick2::PathAnimation::duration
 +    This property holds the duration of the animation, in milliseconds.
 +
 +    The default value is 250.
 +*/
 +int QQuickPathAnimation::duration() const
 +{
 +    Q_D(const QQuickPathAnimation);
 +    return d->duration;
 +}
 +
 +void QQuickPathAnimation::setDuration(int duration)
 +{
 +    if (duration < 0) {
 +        qmlInfo(this) << tr("Cannot set a duration of < 0");
 +        return;
 +    }
 +
 +    Q_D(QQuickPathAnimation);
 +    if (d->duration == duration)
 +        return;
 +    d->duration = duration;
 +    emit durationChanged(duration);
 +}
 +
 +/*!
 +    \qmlproperty enumeration QtQuick2::PathAnimation::easing.type
 +    \qmlproperty real QtQuick2::PathAnimation::easing.amplitude
 +    \qmlproperty list<real> QtQuick2::PathAnimation::easing.bezierCurve
 +    \qmlproperty real QtQuick2::PathAnimation::easing.overshoot
 +    \qmlproperty real QtQuick2::PathAnimation::easing.period
 +    \brief the easing curve used for the animation.
 +
 +    To specify an easing curve you need to specify at least the type. For some curves you can also specify
 +    amplitude, period, overshoot or custom bezierCurve data. The default easing curve is \c Easing.Linear.
 +
 +    See the \l{PropertyAnimation::easing.type} documentation for information
 +    about the different types of easing curves.
 +*/
 +QEasingCurve QQuickPathAnimation::easing() const
 +{
 +    Q_D(const QQuickPathAnimation);
 +    return d->easingCurve;
 +}
 +
 +void QQuickPathAnimation::setEasing(const QEasingCurve &e)
 +{
 +    Q_D(QQuickPathAnimation);
 +    if (d->easingCurve == e)
 +        return;
 +
 +    d->easingCurve = e;
 +    emit easingChanged(e);
 +}
 +
 +/*!
 +    \qmlproperty Path QtQuick2::PathAnimation::path
 +    This property holds the path to animate along.
 +
 +    For more information on defining a path see the \l Path documentation.
 +*/
 +QQuickPath *QQuickPathAnimation::path() const
 +{
 +    Q_D(const QQuickPathAnimation);
 +    return d->path;
 +}
 +
 +void QQuickPathAnimation::setPath(QQuickPath *path)
 +{
 +    Q_D(QQuickPathAnimation);
 +    if (d->path == path)
 +        return;
 +
 +    d->path = path;
 +    emit pathChanged();
 +}
 +
 +/*!
 +    \qmlproperty Item QtQuick2::PathAnimation::target
 +    This property holds the item to animate.
 +*/
 +QQuickItem *QQuickPathAnimation::target() const
 +{
 +    Q_D(const QQuickPathAnimation);
 +    return d->target;
 +}
 +
 +void QQuickPathAnimation::setTargetObject(QQuickItem *target)
 +{
 +    Q_D(QQuickPathAnimation);
 +    if (d->target == target)
 +        return;
 +
 +    d->target = target;
 +    emit targetChanged();
 +}
 +
 +/*!
 +    \qmlproperty enumeration QtQuick2::PathAnimation::orientation
 +    This property controls the rotation of the item as it animates along the path.
 +
 +    If a value other than \c Fixed is specified, the PathAnimation will rotate the
 +    item to achieve the specified orientation as it travels along the path.
 +
 +    \list
 +    \o PathAnimation.Fixed (default) - the PathAnimation will not control
 +       the rotation of the item.
 +    \o PathAnimation.RightFirst - The right side of the item will lead along the path.
 +    \o PathAnimation.LeftFirst - The left side of the item will lead along the path.
 +    \o PathAnimation.BottomFirst - The bottom of the item will lead along the path.
 +    \o PathAnimation.TopFirst - The top of the item will lead along the path.
 +    \endlist
 +*/
 +QQuickPathAnimation::Orientation QQuickPathAnimation::orientation() const
 +{
 +    Q_D(const QQuickPathAnimation);
 +    return d->orientation;
 +}
 +
 +void QQuickPathAnimation::setOrientation(Orientation orientation)
 +{
 +    Q_D(QQuickPathAnimation);
 +    if (d->orientation == orientation)
 +        return;
 +
 +    d->orientation = orientation;
 +    emit orientationChanged(d->orientation);
 +}
 +
 +/*!
 +    \qmlproperty point QtQuick2::PathAnimation::anchorPoint
 +    This property holds the anchor point for the item being animated.
 +
 +    By default, the upper-left corner of the target (its 0,0 point)
 +    will be anchored to (or follow) the path. The anchorPoint property can be used to
 +    specify a different point for anchoring. For example, specifying an anchorPoint of
 +    5,5 for a 10x10 item means the center of the item will follow the path.
 +*/
 +QPointF QQuickPathAnimation::anchorPoint() const
 +{
 +    Q_D(const QQuickPathAnimation);
 +    return d->anchorPoint;
 +}
 +
 +void QQuickPathAnimation::setAnchorPoint(const QPointF &point)
 +{
 +    Q_D(QQuickPathAnimation);
 +    if (d->anchorPoint == point)
 +        return;
 +
 +    d->anchorPoint = point;
 +    emit anchorPointChanged(point);
 +}
 +
 +/*!
 +    \qmlproperty real QtQuick2::PathAnimation::orientationEntryDuration
 +    This property holds the duration (in milliseconds) of the transition in to the orientation.
 +
 +    If an orientation has been specified for the PathAnimation, and the starting
 +    rotation of the item does not match that given by the orientation,
 +    orientationEntryDuration can be used to smoothly transition from the item's
 +    starting rotation to the rotation given by the path orientation.
 +*/
 +int QQuickPathAnimation::orientationEntryDuration() const
 +{
 +    Q_D(const QQuickPathAnimation);
 +    return d->entryDuration;
 +}
 +
 +void QQuickPathAnimation::setOrientationEntryDuration(int duration)
 +{
 +    Q_D(QQuickPathAnimation);
 +    if (d->entryDuration == duration)
 +        return;
 +    d->entryDuration = duration;
 +    emit orientationEntryDurationChanged(duration);
 +}
 +
 +/*!
 +    \qmlproperty real QtQuick2::PathAnimation::orientationExitDuration
 +    This property holds the duration (in milliseconds) of the transition out of the orientation.
 +
 +    If an orientation and endRotation have been specified for the PathAnimation,
 +    orientationExitDuration can be used to smoothly transition from the rotation given
 +    by the path orientation to the specified endRotation.
 +*/
 +int QQuickPathAnimation::orientationExitDuration() const
 +{
 +    Q_D(const QQuickPathAnimation);
 +    return d->exitDuration;
 +}
 +
 +void QQuickPathAnimation::setOrientationExitDuration(int duration)
 +{
 +    Q_D(QQuickPathAnimation);
 +    if (d->exitDuration == duration)
 +        return;
 +    d->exitDuration = duration;
 +    emit orientationExitDurationChanged(duration);
 +}
 +
 +/*!
 +    \qmlproperty real QtQuick2::PathAnimation::endRotation
 +    This property holds the ending rotation for the target.
 +
 +    If an orientation has been specified for the PathAnimation,
 +    and the path doesn't end with the item at the desired rotation,
 +    the endRotation property can be used to manually specify an end
 +    rotation.
 +
 +    This property is typically used with orientationExitDuration, as specifying
 +    an endRotation without an orientationExitDuration may cause a jump to
 +    the final rotation, rather than a smooth transition.
 +*/
 +qreal QQuickPathAnimation::endRotation() const
 +{
 +    Q_D(const QQuickPathAnimation);
 +    return d->endRotation.isNull ? qreal(0) : d->endRotation.value;
 +}
 +
 +void QQuickPathAnimation::setEndRotation(qreal rotation)
 +{
 +    Q_D(QQuickPathAnimation);
 +    if (!d->endRotation.isNull && d->endRotation == rotation)
 +        return;
 +
 +    d->endRotation = rotation;
 +    emit endRotationChanged(d->endRotation);
 +}
 +
 +QAbstractAnimationJob* QQuickPathAnimation::transition(QQuickStateActions &actions,
 +                                           QQmlProperties &modified,
 +                                           TransitionDirection direction,
 +                                           QObject *defaultTarget)
 +{
 +    Q_D(QQuickPathAnimation);
 +
 +    QQuickItem *target = d->target ? d->target : qobject_cast<QQuickItem*>(defaultTarget);
 +
 +    QQuickPathAnimationUpdater prevData;
 +    bool havePrevData = false;
 +    if (d->activeAnimations.contains(target)) {
 +        havePrevData = true;
 +        prevData = *d->activeAnimations[target]->pathUpdater();
 +    }
 +
 +    QList<QQuickItem*> keys = d->activeAnimations.keys();
 +    foreach (QQuickItem *item, keys) {
 +        QQuickPathAnimationAnimator *anim = d->activeAnimations.value(item);
 +        if (anim->state() == QAbstractAnimationJob::Stopped) {
 +            anim->clearTemplate();
 +            d->activeAnimations.remove(item);
 +        }
 +    }
 +
 +    QQuickPathAnimationUpdater *data = new QQuickPathAnimationUpdater();
 +    QQuickPathAnimationAnimator *pa = new QQuickPathAnimationAnimator(d);
 +
 +    d->activeAnimations[target] = pa;
 +
 +    data->orientation = d->orientation;
 +    data->anchorPoint = d->anchorPoint;
 +    data->entryInterval = d->duration ? qreal(d->entryDuration) / d->duration : qreal(0);
 +    data->exitInterval = d->duration ? qreal(d->exitDuration) / d->duration : qreal(0);
 +    data->endRotation = d->endRotation;
 +    data->reverse = direction == Backward ? true : false;
 +    data->fromSourced = false;
 +    data->fromDefined = (d->path && d->path->hasStartX() && d->path->hasStartY()) ? true : false;
 +    data->toDefined = d->path ? d->path->hasEnd() : false;
 +    int origModifiedSize = modified.count();
 +
 +    for (int i = 0; i < actions.count(); ++i) {
 +        QQuickAction &action = actions[i];
 +        if (action.event)
 +            continue;
 +        if (action.specifiedObject == target && action.property.name() == QLatin1String("x")) {
 +            data->toX = action.toValue.toReal();
 +            modified << action.property;
 +            action.fromValue = action.toValue;
 +        }
 +        if (action.specifiedObject == target && action.property.name() == QLatin1String("y")) {
 +            data->toY = action.toValue.toReal();
 +            modified << action.property;
 +            action.fromValue = action.toValue;
 +        }
 +    }
 +
 +    if (target && d->path &&
 +        (modified.count() > origModifiedSize || data->toDefined)) {
 +        data->target = target;
 +        data->path = d->path;
 +        data->path->invalidateSequentialHistory();
 +
 +        if (havePrevData) {
 +            // get the original start angle that was used (so we can exactly reverse).
 +            data->startRotation = prevData.startRotation;
 +
 +            // treat interruptions specially, otherwise we end up with strange paths
 +            if ((data->reverse || prevData.reverse) && prevData.currentV > 0 && prevData.currentV < 1) {
 +                if (!data->fromDefined && !data->toDefined && !prevData.painterPath.isEmpty()) {
 +                    QPointF pathPos = QQuickPath::sequentialPointAt(prevData.painterPath, prevData.pathLength, prevData.attributePoints, prevData.prevBez, prevData.currentV);
 +                    if (!prevData.anchorPoint.isNull())
 +                        pathPos -= prevData.anchorPoint;
 +                    if (pathPos == data->target->pos()) {   //only treat as interruption if we interrupted ourself
 +                        data->painterPath = prevData.painterPath;
 +                        data->toDefined = data->fromDefined = data->fromSourced = true;
 +                        data->prevBez.isValid = false;
 +                        data->interruptStart = prevData.currentV;
 +                        data->startRotation = prevData.startRotation;
 +                        data->pathLength = prevData.pathLength;
 +                        data->attributePoints = prevData.attributePoints;
 +                    }
 +                }
 +            }
 +        }
 +        pa->setFromSourcedValue(&data->fromSourced);
 +        pa->setAnimValue(data);
 +    } else {
 +        pa->setFromSourcedValue(0);
 +        pa->setAnimValue(0);
 +        delete pa;
 +        delete data;
 +    }
 +
 +    pa->setDuration(d->duration);
 +    pa->setEasingCurve(d->easingCurve);
 +    return initInstance(pa);
 +}
 +
 +void QQuickPathAnimationUpdater::setValue(qreal v)
 +{
 +    if (interruptStart.isValid()) {
 +        if (reverse)
 +            v = 1 - v;
 +        qreal end = reverse ? 0.0 : 1.0;
 +        v = interruptStart + v * (end-interruptStart);
 +    }
 +    currentV = v;
 +    bool atStart = ((reverse && v == 1.0) || (!reverse && v == 0.0));
 +    if (!fromSourced && (!fromDefined || !toDefined)) {
 +        qreal startX = reverse ? toX + anchorPoint.x() : target->x() + anchorPoint.x();
 +        qreal startY = reverse ? toY + anchorPoint.y() : target->y() + anchorPoint.y();
 +        qreal endX = reverse ? target->x() + anchorPoint.x() : toX + anchorPoint.x();
 +        qreal endY = reverse ? target->y() + anchorPoint.y() : toY + anchorPoint.y();
 +
 +        prevBez.isValid = false;
 +        painterPath = path->createPath(QPointF(startX, startY), QPointF(endX, endY), QStringList(), pathLength, attributePoints);
 +        fromSourced = true;
 +    }
 +
 +    qreal angle;
 +    bool fixed = orientation == QQuickPathAnimation::Fixed;
 +    QPointF currentPos = !painterPath.isEmpty() ? path->sequentialPointAt(painterPath, pathLength, attributePoints, prevBez, v, fixed ? 0 : &angle) : path->sequentialPointAt(v, fixed ? 0 : &angle);
 +
 +    //adjust position according to anchor point
 +    if (!anchorPoint.isNull()) {
 +        currentPos -= anchorPoint;
 +        if (atStart) {
 +            if (!anchorPoint.isNull() && !fixed)
 +                target->setTransformOriginPoint(anchorPoint);
 +        }
 +    }
 +
 +    target->setPos(currentPos);
 +
 +    //adjust angle according to orientation
 +    if (!fixed) {
 +        switch (orientation) {
 +            case QQuickPathAnimation::RightFirst:
 +                angle = -angle;
 +                break;
 +            case QQuickPathAnimation::TopFirst:
 +                angle = -angle + 90;
 +                break;
 +            case QQuickPathAnimation::LeftFirst:
 +                angle = -angle + 180;
 +                break;
 +            case QQuickPathAnimation::BottomFirst:
 +                angle = -angle + 270;
 +                break;
 +            default:
 +                angle = 0;
 +                break;
 +        }
 +
 +        if (atStart && !reverse) {
 +            startRotation = target->rotation();
 +
 +            //shortest distance to correct orientation
 +            qreal diff = angle - startRotation;
 +            while (diff > 180.0) {
 +                startRotation.value += 360.0;
 +                diff -= 360.0;
 +            }
 +            while (diff < -180.0) {
 +                startRotation.value -= 360.0;
 +                diff += 360.0;
 +            }
 +        }
 +
 +        //smoothly transition to the desired orientation
 +        //TODO: shortest distance calculations
 +        if (startRotation.isValid()) {
 +            if (reverse && v == 0.0)
 +                angle = startRotation;
 +            else if (v < entryInterval)
 +                angle = angle * v / entryInterval + startRotation * (entryInterval - v) / entryInterval;
 +        }
 +        if (endRotation.isValid()) {
 +            qreal exitStart = 1 - entryInterval;
 +            if (!reverse && v == 1.0)
 +                angle = endRotation;
 +            else if (v > exitStart)
 +                angle = endRotation * (v - exitStart) / exitInterval + angle * (exitInterval - (v - exitStart)) / exitInterval;
 +        }
 +        target->setRotation(angle);
 +    }
 +
 +    /*
 +        NOTE: we don't always reset the transform origin, as it can cause a
 +        visual jump if ending on an angle. This means that in some cases
 +        (anchor point and orientation both specified, and ending at an angle)
 +        the transform origin will always be set after running the path animation.
 +     */
 +    if ((reverse && v == 0.0) || (!reverse && v == 1.0)) {
 +        if (!anchorPoint.isNull() && !fixed && qFuzzyIsNull(angle))
 +            target->setTransformOriginPoint(QPointF());
 +    }
 +}
 +
 +QQuickPathAnimationAnimator::QQuickPathAnimationAnimator(QQuickPathAnimationPrivate *priv)
 +    : animationTemplate(priv)
 +{
 +}
 +
 +QQuickPathAnimationAnimator::~QQuickPathAnimationAnimator()
 +{
 +    if (animationTemplate && pathUpdater()) {
 +        QHash<QQuickItem*, QQuickPathAnimationAnimator* >::iterator it =
 +                animationTemplate->activeAnimations.find(pathUpdater()->target);
 +        if (it != animationTemplate->activeAnimations.end() && it.value() == this)
 +            animationTemplate->activeAnimations.erase(it);
 +    }
 +}
 +
 +QT_END_NAMESPACE
@@@ -61,8 -61,9 +61,9 @@@
  #include "qquickvisualdatamodel_p.h"
  #include "qquickgridview_p.h"
  #include "qquickpathview_p.h"
 -#include <private/qdeclarativepath_p.h>
 -#include <private/qdeclarativepathinterpolator_p.h>
+ #include "qquickitemviewtransition_p.h"
 +#include <private/qquickpath_p.h>
 +#include <private/qquickpathinterpolator_p.h>
  #include "qquickpositioners_p.h"
  #include "qquickrepeater_p.h"
  #include "qquickloader_p.h"
@@@ -1225,111 -593,134 +593,134 @@@ void QQuickItemView::setHighlightMoveDu
      }
  }
  
 -QDeclarativeTransition *QQuickItemView::populateTransition() const
 +QQuickTransition *QQuickItemView::populateTransition() const
  {
      Q_D(const QQuickItemView);
-     return d->populateTransition;
+     return d->transitioner ? d->transitioner->populateTransition : 0;
  }
  
 -void QQuickItemView::setPopulateTransition(QDeclarativeTransition *transition)
 +void QQuickItemView::setPopulateTransition(QQuickTransition *transition)
  {
      Q_D(QQuickItemView);
-     if (d->populateTransition != transition) {
-         d->populateTransition = transition;
+     d->createTransitioner();
+     if (d->transitioner->populateTransition != transition) {
+         d->transitioner->populateTransition = transition;
          emit populateTransitionChanged();
      }
  }
  
 -QDeclarativeTransition *QQuickItemView::addTransition() const
 +QQuickTransition *QQuickItemView::addTransition() const
  {
      Q_D(const QQuickItemView);
-     return d->addTransition;
+     return d->transitioner ? d->transitioner->addTransition : 0;
  }
  
 -void QQuickItemView::setAddTransition(QDeclarativeTransition *transition)
 +void QQuickItemView::setAddTransition(QQuickTransition *transition)
  {
      Q_D(QQuickItemView);
-     if (d->addTransition != transition) {
-         d->addTransition = transition;
+     d->createTransitioner();
+     if (d->transitioner->addTransition != transition) {
+         d->transitioner->addTransition = transition;
          emit addTransitionChanged();
      }
  }
  
 -QDeclarativeTransition *QQuickItemView::addDisplacedTransition() const
 +QQuickTransition *QQuickItemView::addDisplacedTransition() const
  {
      Q_D(const QQuickItemView);
-     return d->addDisplacedTransition;
+     return d->transitioner ? d->transitioner->addDisplacedTransition : 0;
  }
  
 -void QQuickItemView::setAddDisplacedTransition(QDeclarativeTransition *transition)
 +void QQuickItemView::setAddDisplacedTransition(QQuickTransition *transition)
  {
      Q_D(QQuickItemView);
-     if (d->addDisplacedTransition != transition) {
-         d->addDisplacedTransition = transition;
+     d->createTransitioner();
+     if (d->transitioner->addDisplacedTransition != transition) {
+         d->transitioner->addDisplacedTransition = transition;
          emit addDisplacedTransitionChanged();
      }
  }
  
 -QDeclarativeTransition *QQuickItemView::moveTransition() const
 +QQuickTransition *QQuickItemView::moveTransition() const
  {
      Q_D(const QQuickItemView);
-     return d->moveTransition;
+     return d->transitioner ? d->transitioner->moveTransition : 0;
  }
  
 -void QQuickItemView::setMoveTransition(QDeclarativeTransition *transition)
 +void QQuickItemView::setMoveTransition(QQuickTransition *transition)
  {
      Q_D(QQuickItemView);
-     if (d->moveTransition != transition) {
-         d->moveTransition = transition;
+     d->createTransitioner();
+     if (d->transitioner->moveTransition != transition) {
+         d->transitioner->moveTransition = transition;
          emit moveTransitionChanged();
      }
  }
  
 -QDeclarativeTransition *QQuickItemView::moveDisplacedTransition() const
 +QQuickTransition *QQuickItemView::moveDisplacedTransition() const
  {
      Q_D(const QQuickItemView);
-     return d->moveDisplacedTransition;
+     return d->transitioner ? d->transitioner->moveDisplacedTransition : 0;
  }
  
 -void QQuickItemView::setMoveDisplacedTransition(QDeclarativeTransition *transition)
 +void QQuickItemView::setMoveDisplacedTransition(QQuickTransition *transition)
  {
      Q_D(QQuickItemView);
-     if (d->moveDisplacedTransition != transition) {
-         d->moveDisplacedTransition = transition;
+     d->createTransitioner();
+     if (d->transitioner->moveDisplacedTransition != transition) {
+         d->transitioner->moveDisplacedTransition = transition;
          emit moveDisplacedTransitionChanged();
      }
  }
  
 -QDeclarativeTransition *QQuickItemView::removeTransition() const
 +QQuickTransition *QQuickItemView::removeTransition() const
  {
      Q_D(const QQuickItemView);
-     return d->removeTransition;
+     return d->transitioner ? d->transitioner->removeTransition : 0;
  }
  
 -void QQuickItemView::setRemoveTransition(QDeclarativeTransition *transition)
 +void QQuickItemView::setRemoveTransition(QQuickTransition *transition)
  {
      Q_D(QQuickItemView);
-     if (d->removeTransition != transition) {
-         d->removeTransition = transition;
+     d->createTransitioner();
+     if (d->transitioner->removeTransition != transition) {
+         d->transitioner->removeTransition = transition;
          emit removeTransitionChanged();
      }
  }
  
 -QDeclarativeTransition *QQuickItemView::removeDisplacedTransition() const
 +QQuickTransition *QQuickItemView::removeDisplacedTransition() const
  {
      Q_D(const QQuickItemView);
-     return d->removeDisplacedTransition;
+     return d->transitioner ? d->transitioner->removeDisplacedTransition : 0;
  }
  
 -void QQuickItemView::setRemoveDisplacedTransition(QDeclarativeTransition *transition)
 +void QQuickItemView::setRemoveDisplacedTransition(QQuickTransition *transition)
  {
      Q_D(QQuickItemView);
-     if (d->removeDisplacedTransition != transition) {
-         d->removeDisplacedTransition = transition;
+     d->createTransitioner();
+     if (d->transitioner->removeDisplacedTransition != transition) {
+         d->transitioner->removeDisplacedTransition = transition;
          emit removeDisplacedTransitionChanged();
      }
  }
  
 -QDeclarativeTransition *QQuickItemView::displacedTransition() const
++QQuickTransition *QQuickItemView::displacedTransition() const
+ {
+     Q_D(const QQuickItemView);
+     return d->transitioner ? d->transitioner->displacedTransition : 0;
+ }
 -void QQuickItemView::setDisplacedTransition(QDeclarativeTransition *transition)
++void QQuickItemView::setDisplacedTransition(QQuickTransition *transition)
+ {
+     Q_D(QQuickItemView);
+     d->createTransitioner();
+     if (d->transitioner->displacedTransition != transition) {
+         d->transitioner->displacedTransition = transition;
+         emit displacedTransitionChanged();
+     }
+ }
  void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
  {
      Q_Q(QQuickItemView);
@@@ -1464,65 -855,7 +855,7 @@@ void QQuickItemViewPrivate::applyPendin
          layout();
  }
  
- bool QQuickItemViewPrivate::canTransition(FxViewItemTransitionManager::TransitionType type, bool asTarget) const
- {
-     switch (type) {
-     case FxViewItemTransitionManager::NoTransition:
-         break;
-     case FxViewItemTransitionManager::PopulateTransition:
-         return usePopulateTransition
-                 && populateTransition && populateTransition->enabled();
-     case FxViewItemTransitionManager::AddTransition:
-         if (asTarget)
-             return addTransition && addTransition->enabled();
-         else
-             return addDisplacedTransition && addDisplacedTransition->enabled();
-     case FxViewItemTransitionManager::MoveTransition:
-         if (asTarget)
-             return moveTransition && moveTransition->enabled();
-         else
-             return moveDisplacedTransition && moveDisplacedTransition->enabled();
-     case FxViewItemTransitionManager::RemoveTransition:
-         if (asTarget)
-             return removeTransition && removeTransition->enabled();
-         else
-             return removeDisplacedTransition && removeDisplacedTransition->enabled();
-     }
-     return false;
- }
- bool QQuickItemViewPrivate::hasItemTransitions() const
- {
-     return canTransition(FxViewItemTransitionManager::PopulateTransition, true)
-             || canTransition(FxViewItemTransitionManager::AddTransition, true)
-             || canTransition(FxViewItemTransitionManager::AddTransition, false)
-             || canTransition(FxViewItemTransitionManager::MoveTransition, true)
-             || canTransition(FxViewItemTransitionManager::MoveTransition, false)
-             || canTransition(FxViewItemTransitionManager::RemoveTransition, true)
-             || canTransition(FxViewItemTransitionManager::RemoveTransition, false);
- }
- void QQuickItemViewPrivate::transitionNextReposition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, bool isTarget)
- {
-     bool matchedTransition = false;
-     if (type == FxViewItemTransitionManager::AddTransition) {
-         // don't run add transitions for added items while populating
-         matchedTransition = !usePopulateTransition && canTransition(type, isTarget);
-     } else {
-         matchedTransition = canTransition(type, isTarget);
-     }
-     if (matchedTransition) {
-         item->setNextTransition(type, isTarget);
-     } else {
-         // the requested transition type is not valid, but the item is scheduled/in another
-         // transition, so cancel it to allow the item to move directly to the correct pos
-         if (item->transitionScheduledOrRunning())
-             item->stopTransition();
-     }
- }
 -int QQuickItemViewPrivate::findMoveKeyIndex(QDeclarativeChangeSet::MoveKey key, const QVector<QDeclarativeChangeSet::Remove> &changes) const
 +int QQuickItemViewPrivate::findMoveKeyIndex(QQuickChangeSet::MoveKey key, const QVector<QQuickChangeSet::Remove> &changes) const
  {
      for (int i=0; i<changes.count(); i++) {
          for (int j=changes[i].index; j<changes[i].index + changes[i].count; j++) {
@@@ -2543,10 -1892,11 +1892,11 @@@ void QQuickItemViewPrivate::removeItem(
      }
      if (removal.isMove()) {
          currentChanges.removedItems.insert(removal.moveKey(item->index), item);
-         transitionNextReposition(item, FxViewItemTransitionManager::MoveTransition, true);
+         if (transitioner)
+             transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::MoveTransition, true);
      } else {
          // track item so it is released later
 -        currentChanges.removedItems.insertMulti(QDeclarativeChangeSet::MoveKey(), item);
 +        currentChanges.removedItems.insertMulti(QQuickChangeSet::MoveKey(), item);
      }
      if (!removeResult->changedFirstItem && item == *visibleItems.constBegin())
          removeResult->changedFirstItem = true;
@@@ -2629,13 -1987,16 +1987,16 @@@ void QQuickItemViewPrivate::prepareVisi
      }
  }
  
 -void QQuickItemViewPrivate::prepareRemoveTransitions(QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *> *removedItems)
 +void QQuickItemViewPrivate::prepareRemoveTransitions(QHash<QQuickChangeSet::MoveKey, FxViewItem *> *removedItems)
  {
-     removeTransitionIndexes.clear();
-     removeTransitionTargets.clear();
+     if (!transitioner)
+         return;
  
-     if (canTransition(FxViewItemTransitionManager::RemoveTransition, true)) {
+     transitioner->removeTransitionIndexes.clear();
+     transitioner->removeTransitionTargets.clear();
+     if (transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)) {
 -        for (QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *>::Iterator it = removedItems->begin();
 +        for (QHash<QQuickChangeSet::MoveKey, FxViewItem *>::Iterator it = removedItems->begin();
               it != removedItems->end(); ) {
              bool isRemove = it.key().moveId < 0;
              if (isRemove) {
@@@ -48,9 -48,9 +48,9 @@@ QT_BEGIN_HEADE
  
  QT_BEGIN_NAMESPACE
  
- QT_MODULE(Qml)
 -QT_MODULE(Declarative)
++QT_MODULE(Quick)
  
 -class QDeclarativeChangeSet;
 +class QQuickChangeSet;
  
  class QQuickItemViewPrivate;
  
@@@ -71,20 -71,21 +71,21 @@@ class Q_AUTOTEST_EXPORT QQuickItemView 
      Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
      Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
  
 -    Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
 +    Q_PROPERTY(QQmlComponent *header READ header WRITE setHeader NOTIFY headerChanged)
      Q_PROPERTY(QQuickItem *headerItem READ headerItem NOTIFY headerItemChanged)
 -    Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
 +    Q_PROPERTY(QQmlComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
      Q_PROPERTY(QQuickItem *footerItem READ footerItem NOTIFY footerItemChanged)
  
 -    Q_PROPERTY(QDeclarativeTransition *populate READ populateTransition WRITE setPopulateTransition NOTIFY populateTransitionChanged)
 -    Q_PROPERTY(QDeclarativeTransition *add READ addTransition WRITE setAddTransition NOTIFY addTransitionChanged)
 -    Q_PROPERTY(QDeclarativeTransition *addDisplaced READ addDisplacedTransition WRITE setAddDisplacedTransition NOTIFY addDisplacedTransitionChanged)
 -    Q_PROPERTY(QDeclarativeTransition *move READ moveTransition WRITE setMoveTransition NOTIFY moveTransitionChanged)
 -    Q_PROPERTY(QDeclarativeTransition *moveDisplaced READ moveDisplacedTransition WRITE setMoveDisplacedTransition NOTIFY moveDisplacedTransitionChanged)
 -    Q_PROPERTY(QDeclarativeTransition *remove READ removeTransition WRITE setRemoveTransition NOTIFY removeTransitionChanged)
 -    Q_PROPERTY(QDeclarativeTransition *removeDisplaced READ removeDisplacedTransition WRITE setRemoveDisplacedTransition NOTIFY removeDisplacedTransitionChanged)
 -    Q_PROPERTY(QDeclarativeTransition *displaced READ displacedTransition WRITE setDisplacedTransition NOTIFY displacedTransitionChanged)
 +    Q_PROPERTY(QQuickTransition *populate READ populateTransition WRITE setPopulateTransition NOTIFY populateTransitionChanged)
 +    Q_PROPERTY(QQuickTransition *add READ addTransition WRITE setAddTransition NOTIFY addTransitionChanged)
 +    Q_PROPERTY(QQuickTransition *addDisplaced READ addDisplacedTransition WRITE setAddDisplacedTransition NOTIFY addDisplacedTransitionChanged)
 +    Q_PROPERTY(QQuickTransition *move READ moveTransition WRITE setMoveTransition NOTIFY moveTransitionChanged)
 +    Q_PROPERTY(QQuickTransition *moveDisplaced READ moveDisplacedTransition WRITE setMoveDisplacedTransition NOTIFY moveDisplacedTransitionChanged)
 +    Q_PROPERTY(QQuickTransition *remove READ removeTransition WRITE setRemoveTransition NOTIFY removeTransitionChanged)
 +    Q_PROPERTY(QQuickTransition *removeDisplaced READ removeDisplacedTransition WRITE setRemoveDisplacedTransition NOTIFY removeDisplacedTransitionChanged)
++    Q_PROPERTY(QQuickTransition *displaced READ displacedTransition WRITE setDisplacedTransition NOTIFY displacedTransitionChanged)
  
 -    Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
 +    Q_PROPERTY(QQmlComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
      Q_PROPERTY(QQuickItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
      Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged)
      Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
@@@ -122,37 -123,40 +123,40 @@@ public
      void setLayoutDirection(Qt::LayoutDirection);
      Qt::LayoutDirection effectiveLayoutDirection() const;
  
 -    QDeclarativeComponent *footer() const;
 -    void setFooter(QDeclarativeComponent *);
 +    QQmlComponent *footer() const;
 +    void setFooter(QQmlComponent *);
      QQuickItem *footerItem() const;
  
 -    QDeclarativeComponent *header() const;
 -    void setHeader(QDeclarativeComponent *);
 +    QQmlComponent *header() const;
 +    void setHeader(QQmlComponent *);
      QQuickItem *headerItem() const;
  
 -    QDeclarativeTransition *populateTransition() const;
 -    void setPopulateTransition(QDeclarativeTransition *transition);
 +    QQuickTransition *populateTransition() const;
 +    void setPopulateTransition(QQuickTransition *transition);
  
 -    QDeclarativeTransition *addTransition() const;
 -    void setAddTransition(QDeclarativeTransition *transition);
 +    QQuickTransition *addTransition() const;
 +    void setAddTransition(QQuickTransition *transition);
  
 -    QDeclarativeTransition *addDisplacedTransition() const;
 -    void setAddDisplacedTransition(QDeclarativeTransition *transition);
 +    QQuickTransition *addDisplacedTransition() const;
 +    void setAddDisplacedTransition(QQuickTransition *transition);
  
 -    QDeclarativeTransition *moveTransition() const;
 -    void setMoveTransition(QDeclarativeTransition *transition);
 +    QQuickTransition *moveTransition() const;
 +    void setMoveTransition(QQuickTransition *transition);
  
 -    QDeclarativeTransition *moveDisplacedTransition() const;
 -    void setMoveDisplacedTransition(QDeclarativeTransition *transition);
 +    QQuickTransition *moveDisplacedTransition() const;
 +    void setMoveDisplacedTransition(QQuickTransition *transition);
  
 -    QDeclarativeTransition *removeTransition() const;
 -    void setRemoveTransition(QDeclarativeTransition *transition);
 +    QQuickTransition *removeTransition() const;
 +    void setRemoveTransition(QQuickTransition *transition);
  
 -    QDeclarativeTransition *removeDisplacedTransition() const;
 -    void setRemoveDisplacedTransition(QDeclarativeTransition *transition);
 +    QQuickTransition *removeDisplacedTransition() const;
 +    void setRemoveDisplacedTransition(QQuickTransition *transition);
  
 -    QDeclarativeTransition *displacedTransition() const;
 -    void setDisplacedTransition(QDeclarativeTransition *transition);
++    QQuickTransition *displacedTransition() const;
++    void setDisplacedTransition(QQuickTransition *transition);
 -    QDeclarativeComponent *highlight() const;
 -    void setHighlight(QDeclarativeComponent *);
 +    QQmlComponent *highlight() const;
 +    void setHighlight(QQmlComponent *);
  
      QQuickItem *highlightItem() const;
  
  #include "qquickflickable_p_p.h"
  #include "qquickvisualdatamodel_p.h"
  #include "qquickvisualitemmodel_p.h"
- #include <private/qquicktransitionmanager_p_p.h>
 -#include <private/qdeclarativechangeset_p.h>
 +#include <private/qquickchangeset_p.h>
  
  
  QT_BEGIN_HEADER
  
  QT_BEGIN_NAMESPACE
  
--QT_MODULE(Declarative)
++QT_MODULE(Quick)
  
  
- class FxViewItem;
- class FxViewItemTransitionManager : public QQuickTransitionManager
- {
- public:
-     enum TransitionType {
-         NoTransition,
-         PopulateTransition,
-         AddTransition,
-         MoveTransition,
-         RemoveTransition
-     };
-     FxViewItemTransitionManager();
-     ~FxViewItemTransitionManager();
-     bool isActive() const;
-     void startTransition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, const QPointF &to, bool isTargetItem);
-     bool m_active;
-     FxViewItem *m_item;
-     QPointF m_toPos;
-     FxViewItemTransitionManager::TransitionType m_type;
-     bool m_isTarget;
- protected:
-     virtual void finished();
- };
- class FxViewItem
+ class FxViewItem : public QQuickViewItem
  {
  public:
      FxViewItem(QQuickItem *, bool own);
@@@ -160,9 -104,10 +104,10 @@@ class QQuickItemViewPrivate : public QQ
      Q_DECLARE_PUBLIC(QQuickItemView)
  public:
      QQuickItemViewPrivate();
+     ~QQuickItemViewPrivate();
  
      struct ChangeResult {
 -        QDeclarativeNullableValue<qreal> visiblePos;
 +        QQmlNullableValue<qreal> visiblePos;
          bool changedFirstItem;
          qreal sizeChangesBeforeVisiblePos;
          qreal sizeChangesAfterVisiblePos;
      void mirrorChange();
  
      FxViewItem *createItem(int modelIndex, bool asynchronous = false);
-     virtual void releaseItem(FxViewItem *item);
+     virtual bool releaseItem(FxViewItem *item);
  
      QQuickItem *createHighlightItem();
 -    QQuickItem *createComponentItem(QDeclarativeComponent *component, bool receiveItemGeometryChanges, bool createDefault = false);
 +    QQuickItem *createComponentItem(QQmlComponent *component, bool receiveItemGeometryChanges, bool createDefault = false);
  
      void updateCurrent(int modelIndex);
      void updateTrackedItem();
      void repositionFirstItem(FxViewItem *prevVisibleItemsFirst, qreal prevVisibleItemsFirstPos,
              FxViewItem *prevFirstVisible, ChangeResult *insertionResult, ChangeResult *removalResult);
  
+     void createTransitioner();
      void prepareVisibleItemTransitions();
 -    void prepareRemoveTransitions(QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *> *removedItems);
 +    void prepareRemoveTransitions(QHash<QQuickChangeSet::MoveKey, FxViewItem *> *removedItems);
      bool prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds);
+     virtual void viewItemTransitionFinished(QQuickViewItem *item);
  
-     bool canTransition(FxViewItemTransitionManager::TransitionType type, bool asTarget) const;
-     bool hasItemTransitions() const;
-     void transitionNextReposition(FxViewItem *item, FxViewItemTransitionManager::TransitionType type, bool isTarget);
 -    int findMoveKeyIndex(QDeclarativeChangeSet::MoveKey key, const QVector<QDeclarativeChangeSet::Remove> &changes) const;
 +    int findMoveKeyIndex(QQuickChangeSet::MoveKey key, const QVector<QQuickChangeSet::Remove> &changes) const;
  
      void checkVisible() const;
      void showVisibleItems() const;
      FxViewItem *requestedItem;
      QQuickItemViewChangeSet currentChanges;
  
-     // XXX split into struct
 -    QDeclarativeComponent *highlightComponent;
 +    QQmlComponent *highlightComponent;
      FxViewItem *highlight;
      int highlightRange;     // enum value
      qreal highlightRangeStart;
      qreal highlightRangeEnd;
      int highlightMoveDuration;
  
 -    QDeclarativeComponent *headerComponent;
 +    QQmlComponent *headerComponent;
      FxViewItem *header;
 -    QDeclarativeComponent *footerComponent;
 +    QQmlComponent *footerComponent;
      FxViewItem *footer;
  
-     QQuickTransition *populateTransition;
-     QQuickTransition *addTransition;
-     QQuickTransition *addDisplacedTransition;
-     QQuickTransition *moveTransition;
-     QQuickTransition *moveDisplacedTransition;
-     QQuickTransition *removeTransition;
-     QQuickTransition *removeDisplacedTransition;
-     QList<int> addTransitionIndexes;
-     QList<int> moveTransitionIndexes;
-     QList<int> removeTransitionIndexes;
-     QList<QObject *> addTransitionTargets;
-     QList<QObject *> moveTransitionTargets;
-     QList<QObject *> removeTransitionTargets;
      struct MovedItem {
          FxViewItem *item;
 -        QDeclarativeChangeSet::MoveKey moveKey;
 -        MovedItem(FxViewItem *i, QDeclarativeChangeSet::MoveKey k)
 +        QQuickChangeSet::MoveKey moveKey;
 +        MovedItem(FxViewItem *i, QQuickChangeSet::MoveKey k)
              : item(i), moveKey(k) {}
      };
+     QQuickItemViewTransitioner *transitioner;
      QList<FxViewItem *> releasePendingTransition;
  
      mutable qreal minExtent;
index 0000000,3febc9b..54375bf
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,876 +1,876 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
 -#include <QtQuick/private/qdeclarativetransition_p.h>
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #include "qquickitemviewtransition_p.h"
+ #include <QtQuick/qquickitem.h>
 -class QQuickItemViewTransitionJob : public QDeclarativeTransitionManager
++#include <QtQuick/private/qquicktransition_p.h>
+ QT_BEGIN_NAMESPACE
+ static QList<int> qquickitemviewtransition_emptyIndexes = QList<int>();
+ static QList<QObject *> qquickitemviewtransition_emptyTargets = QList<QObject *>();
 -    QDeclarativeTransition *trans = transitioner->transitionObject(type, isTargetItem);
++class QQuickItemViewTransitionJob : public QQuickTransitionManager
+ {
+ public:
+     QQuickItemViewTransitionJob();
+     ~QQuickItemViewTransitionJob();
+     void startTransition(QQuickViewItem *item, QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, const QPointF &to, bool isTargetItem);
+     QQuickItemViewTransitioner *m_transitioner;
+     QQuickViewItem *m_item;
+     QPointF m_toPos;
+     QQuickItemViewTransitioner::TransitionType m_type;
+     bool m_isTarget;
+ protected:
+     virtual void finished();
+ };
+ QQuickItemViewTransitionJob::QQuickItemViewTransitionJob()
+     : m_transitioner(0)
+     , m_item(0)
+     , m_type(QQuickItemViewTransitioner::NoTransition)
+     , m_isTarget(false)
+ {
+ }
+ QQuickItemViewTransitionJob::~QQuickItemViewTransitionJob()
+ {
+     if (m_transitioner)
+         m_transitioner->runningJobs.remove(this);
+ }
+ void QQuickItemViewTransitionJob::startTransition(QQuickViewItem *item, QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, const QPointF &to, bool isTargetItem)
+ {
+     if (type == QQuickItemViewTransitioner::NoTransition)
+         return;
+     if (!item) {
+         qWarning("startTransition(): invalid item");
+         return;
+     }
+     if (!transitioner) {
+         qWarning("startTransition(): invalid transitioner");
+         return;
+     }
 -    QDeclarativeStateOperation::ActionList actions;
 -    actions << QDeclarativeAction(item->item, QLatin1String("x"), QVariant(to.x()));
 -    actions << QDeclarativeAction(item->item, QLatin1String("y"), QVariant(to.y()));
++    QQuickTransition *trans = transitioner->transitionObject(type, isTargetItem);
+     if (!trans) {
+         qWarning("QQuickItemView: invalid view transition!");
+         return;
+     }
+     m_item = item;
+     m_transitioner = transitioner;
+     m_toPos = to;
+     m_type = type;
+     m_isTarget = isTargetItem;
+     QQuickViewTransitionAttached *attached =
+             static_cast<QQuickViewTransitionAttached*>(qmlAttachedPropertiesObject<QQuickViewTransitionAttached>(trans));
+     if (attached) {
+         attached->m_index = item->index;
+         attached->m_item = item->item;
+         attached->m_destination = to;
+         attached->m_targetIndexes = m_transitioner->targetIndexes(type);
+         attached->m_targetItems = m_transitioner->targetItems(type);
+         emit attached->indexChanged();
+         emit attached->itemChanged();
+         emit attached->destinationChanged();
+         emit attached->targetIndexesChanged();
+         emit attached->targetItemsChanged();
+     }
 -    QDeclarativeTransitionManager::transition(actions, trans, item->item);
++    QQuickStateOperation::ActionList actions;
++    actions << QQuickAction(item->item, QLatin1String("x"), QVariant(to.x()));
++    actions << QQuickAction(item->item, QLatin1String("y"), QVariant(to.y()));
+     m_transitioner->runningJobs << this;
 -    QDeclarativeTransitionManager::finished();
++    QQuickTransitionManager::transition(actions, trans, item->item);
+ }
+ void QQuickItemViewTransitionJob::finished()
+ {
 -QDeclarativeTransition *QQuickItemViewTransitioner::transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget)
++    QQuickTransitionManager::finished();
+     if (m_transitioner)
+         m_transitioner->finishedTransition(this, m_item);
+     m_item = 0;
+     m_toPos.setX(0);
+     m_toPos.setY(0);
+     m_type = QQuickItemViewTransitioner::NoTransition;
+     m_isTarget = false;
+ }
+ QQuickItemViewTransitioner::QQuickItemViewTransitioner()
+     : populateTransition(0)
+     , addTransition(0), addDisplacedTransition(0)
+     , moveTransition(0), moveDisplacedTransition(0)
+     , removeTransition(0), removeDisplacedTransition(0)
+     , displacedTransition(0)
+     , changeListener(0)
+     , usePopulateTransition(false)
+ {
+ }
+ QQuickItemViewTransitioner::~QQuickItemViewTransitioner()
+ {
+     for (QSet<QQuickItemViewTransitionJob *>::iterator it = runningJobs.begin(); it != runningJobs.end(); ++it)
+         (*it)->m_transitioner = 0;
+ }
+ bool QQuickItemViewTransitioner::canTransition(QQuickItemViewTransitioner::TransitionType type, bool asTarget) const
+ {
+     if (!asTarget
+             && type != QQuickItemViewTransitioner::NoTransition && type != QQuickItemViewTransitioner::PopulateTransition
+             && displacedTransition && displacedTransition->enabled()) {
+         return true;
+     }
+     switch (type) {
+     case QQuickItemViewTransitioner::NoTransition:
+         break;
+     case QQuickItemViewTransitioner::PopulateTransition:
+         return usePopulateTransition
+                 && populateTransition && populateTransition->enabled();
+     case QQuickItemViewTransitioner::AddTransition:
+         if (asTarget)
+             return addTransition && addTransition->enabled();
+         else
+             return addDisplacedTransition && addDisplacedTransition->enabled();
+     case QQuickItemViewTransitioner::MoveTransition:
+         if (asTarget)
+             return moveTransition && moveTransition->enabled();
+         else
+             return moveDisplacedTransition && moveDisplacedTransition->enabled();
+     case QQuickItemViewTransitioner::RemoveTransition:
+         if (asTarget)
+             return removeTransition && removeTransition->enabled();
+         else
+             return removeDisplacedTransition && removeDisplacedTransition->enabled();
+     }
+     return false;
+ }
+ void QQuickItemViewTransitioner::transitionNextReposition(QQuickViewItem *item, QQuickItemViewTransitioner::TransitionType type, bool isTarget)
+ {
+     bool matchedTransition = false;
+     if (type == QQuickItemViewTransitioner::AddTransition) {
+         // don't run add transitions for added items while populating
+         if (usePopulateTransition)
+             matchedTransition = false;
+         else
+             matchedTransition = canTransition(type, isTarget);
+     } else {
+         matchedTransition = canTransition(type, isTarget);
+     }
+     if (matchedTransition) {
+         item->setNextTransition(type, isTarget);
+     } else {
+         // the requested transition type is not valid, but the item is scheduled/in another
+         // transition, so cancel it to allow the item to move directly to the correct pos
+         if (item->transitionScheduledOrRunning())
+             item->stopTransition();
+     }
+ }
 -    QDeclarativeTransition *trans = 0;
++QQuickTransition *QQuickItemViewTransitioner::transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget)
+ {
+     if (type == QQuickItemViewTransitioner::NoTransition)
+         return 0;
+     if (type == PopulateTransition)
+         asTarget = true;    // no separate displaced transition
 -QDeclarativeListProperty<QObject> QQuickViewTransitionAttached::targetItems()
++    QQuickTransition *trans = 0;
+     switch (type) {
+     case NoTransition:
+         break;
+     case PopulateTransition:
+         trans = populateTransition;
+         break;
+     case AddTransition:
+         trans = asTarget ? addTransition : addDisplacedTransition;
+         break;
+     case MoveTransition:
+         trans = asTarget ? moveTransition : moveDisplacedTransition;
+         break;
+     case RemoveTransition:
+         trans = asTarget ? removeTransition : removeDisplacedTransition;
+         break;
+     }
+     if (!asTarget && (!trans || !trans->enabled()))
+         trans = displacedTransition;
+     if (trans && trans->enabled())
+         return trans;
+     return 0;
+ }
+ const QList<int> &QQuickItemViewTransitioner::targetIndexes(QQuickItemViewTransitioner::TransitionType type) const
+ {
+     switch (type) {
+     case QQuickItemViewTransitioner::NoTransition:
+         break;
+     case QQuickItemViewTransitioner::PopulateTransition:
+     case QQuickItemViewTransitioner::AddTransition:
+         return addTransitionIndexes;
+     case QQuickItemViewTransitioner::MoveTransition:
+         return moveTransitionIndexes;
+     case QQuickItemViewTransitioner::RemoveTransition:
+         return removeTransitionIndexes;
+     }
+     return qquickitemviewtransition_emptyIndexes;
+ }
+ const QList<QObject *> &QQuickItemViewTransitioner::targetItems(QQuickItemViewTransitioner::TransitionType type) const
+ {
+     switch (type) {
+     case QQuickItemViewTransitioner::NoTransition:
+         break;
+     case QQuickItemViewTransitioner::PopulateTransition:
+     case QQuickItemViewTransitioner::AddTransition:
+         return addTransitionTargets;
+     case QQuickItemViewTransitioner::MoveTransition:
+         return moveTransitionTargets;
+     case QQuickItemViewTransitioner::RemoveTransition:
+         return removeTransitionTargets;
+     }
+     return qquickitemviewtransition_emptyTargets;
+ }
+ void QQuickItemViewTransitioner::finishedTransition(QQuickItemViewTransitionJob *job, QQuickViewItem *item)
+ {
+     if (!runningJobs.contains(job))
+         return;
+     runningJobs.remove(job);
+     if (item) {
+         item->finishedTransition();
+         if (changeListener)
+             changeListener->viewItemTransitionFinished(item);
+     }
+ }
+ QQuickViewItem::QQuickViewItem(QQuickItem *i)
+     : item(i)
+     , transition(0)
+     , nextTransitionType(QQuickItemViewTransitioner::NoTransition)
+     , index(-1)
+     , isTransitionTarget(false)
+     , nextTransitionToSet(false)
+ {
+ }
+ QQuickViewItem::~QQuickViewItem()
+ {
+     delete transition;
+ }
+ qreal QQuickViewItem::itemX() const
+ {
+     if (nextTransitionType != QQuickItemViewTransitioner::NoTransition)
+         return nextTransitionToSet ? nextTransitionTo.x() : item->x();
+     else if (transition && transition->isRunning())
+         return transition->m_toPos.x();
+     else
+         return item->x();
+ }
+ qreal QQuickViewItem::itemY() const
+ {
+     // If item is transitioning to some pos, return that dest pos.
+     // If item was redirected to some new pos before the current transition finished,
+     // return that new pos.
+     if (nextTransitionType != QQuickItemViewTransitioner::NoTransition)
+         return nextTransitionToSet ? nextTransitionTo.y() : item->y();
+     else if (transition && transition->isRunning())
+         return transition->m_toPos.y();
+     else
+         return item->y();
+ }
+ void QQuickViewItem::moveTo(const QPointF &pos)
+ {
+     if (transitionScheduledOrRunning()) {
+         nextTransitionTo = pos;
+         nextTransitionToSet = true;
+     } else {
+         item->setPos(pos);
+     }
+ }
+ void QQuickViewItem::setVisible(bool visible)
+ {
+     if (!visible && transitionScheduledOrRunning())
+         return;
+     item->setVisible(visible);
+ }
+ bool QQuickViewItem::transitionScheduledOrRunning() const
+ {
+     return (transition && transition->isRunning())
+             || nextTransitionType != QQuickItemViewTransitioner::NoTransition;
+ }
+ bool QQuickViewItem::transitionRunning() const
+ {
+     return (transition && transition->isRunning());
+ }
+ bool QQuickViewItem::isPendingRemoval() const
+ {
+     if (nextTransitionType == QQuickItemViewTransitioner::RemoveTransition)
+         return isTransitionTarget;
+     if (transition && transition->isRunning() && transition->m_type == QQuickItemViewTransitioner::RemoveTransition)
+         return transition->m_isTarget;
+     return false;
+ }
+ bool QQuickViewItem::prepareTransition(const QRectF &viewBounds)
+ {
+     bool doTransition = false;
+     // If item is not already moving somewhere, set it to not move anywhere.
+     // This ensures that removed targets don't transition to the default (0,0) and that
+     // items set for other transition types only transition if they actually move somewhere.
+     if (nextTransitionType != QQuickItemViewTransitioner::NoTransition && !nextTransitionToSet)
+         moveTo(item->pos());
+     // For move transitions (both target and displaced) and displaced transitions of other
+     // types, only run the transition if the item is actually moving to another position.
+     switch (nextTransitionType) {
+     case QQuickItemViewTransitioner::NoTransition:
+     {
+         return false;
+     }
+     case QQuickItemViewTransitioner::PopulateTransition:
+     {
+         return true;
+     }
+     case QQuickItemViewTransitioner::AddTransition:
+     case QQuickItemViewTransitioner::RemoveTransition:
+         if (viewBounds.isNull()) {
+             if (isTransitionTarget)
+                 doTransition = true;
+             else
+                 doTransition = transitionWillChangePosition();
+         } else if (isTransitionTarget) {
+             // For Add targets, do transition if item is moving into visible area
+             // For Remove targets, do transition if item is currently in visible area
+             doTransition = (nextTransitionType == QQuickItemViewTransitioner::AddTransition)
+                     ? viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()))
+                     : viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()));
+             if (!doTransition)
+                 item->setPos(nextTransitionTo);
+         } else {
+             if (viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()))
+                     || viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()))) {
+                 doTransition = transitionWillChangePosition();
+             } else {
+                 item->setPos(nextTransitionTo);
+             }
+         }
+         break;
+     case QQuickItemViewTransitioner::MoveTransition:
+         // do transition if moving from or into visible area
+         if (transitionWillChangePosition()) {
+             doTransition = viewBounds.isNull()
+                     || viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()))
+                     || viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()));
+             if (!doTransition)
+                 item->setPos(nextTransitionTo);
+         }
+         break;
+     }
+     if (!doTransition)
+         resetTransitionData();
+     return doTransition;
+ }
+ void QQuickViewItem::startTransition(QQuickItemViewTransitioner *transitioner)
+ {
+     if (nextTransitionType == QQuickItemViewTransitioner::NoTransition)
+         return;
+     if (!transition || transition->m_type != nextTransitionType || transition->m_isTarget != isTransitionTarget) {
+         delete transition;
+         transition = new QQuickItemViewTransitionJob;
+     }
+     // if item is not already moving somewhere, set it to not move anywhere
+     // so that removed items do not move to the default (0,0)
+     if (!nextTransitionToSet)
+         moveTo(item->pos());
+     transition->startTransition(this, transitioner, nextTransitionType, nextTransitionTo, isTransitionTarget);
+     nextTransitionType = QQuickItemViewTransitioner::NoTransition;
+ }
+ void QQuickViewItem::stopTransition()
+ {
+     if (transition) {
+         transition->cancel();
+         delete transition;
+         transition = 0;
+     }
+     resetTransitionData();
+     finishedTransition();
+ }
+ void QQuickViewItem::setNextTransition(QQuickItemViewTransitioner::TransitionType type, bool isTargetItem)
+ {
+     // Don't reset nextTransitionToSet - once it is set, it cannot be changed
+     // until the animation finishes since the itemX() and itemY() may be used
+     // to calculate positions for transitions for other items in the view.
+     nextTransitionType = type;
+     isTransitionTarget = isTargetItem;
+ }
+ bool QQuickViewItem::transitionWillChangePosition() const
+ {
+     if (transitionRunning() && transition->m_toPos != nextTransitionTo)
+         return true;
+     return nextTransitionTo != item->pos();
+ }
+ void QQuickViewItem::finishedTransition()
+ {
+     nextTransitionToSet = false;
+     nextTransitionTo = QPointF();
+ }
+ void QQuickViewItem::resetTransitionData()
+ {
+     nextTransitionType = QQuickItemViewTransitioner::NoTransition;
+     isTransitionTarget = false;
+     nextTransitionTo = QPointF();
+     nextTransitionToSet = false;
+ }
+ QQuickViewTransitionAttached::QQuickViewTransitionAttached(QObject *parent)
+     : QObject(parent), m_item(0), m_index(-1)
+ {
+ }
+ /*!
+     \qmlclass ViewTransition QQuickViewTransitionAttached
+     \inqmlmodule QtQuick 2
+     \ingroup qml-view-elements
+     \brief The ViewTransition attached property provides details on items under transition in a view.
+     With ListView and GridView, it is possible to specify transitions that should be applied whenever
+     the items in the view change as a result of modifications to the view's model. They both have the
+     following properties that can be set to the appropriate transitions to be run for various
+     operations:
+     \list
+     \o \c populate - the transition to run when a view is created, or when the model changes
+     \o \c add - the transition to apply to items that are added to the view
+     \o \c remove - the transition to apply to items that are removed from the view
+     \o \c move - the transition to apply to items that are moved within the view (i.e. as a result
+        of a move operation in the model)
+     \o \c displaced - the generic transition to be applied to any items that are displaced by an
+        add, move or remove operation
+     \o \c addDisplaced, \c removeDisplaced and \c moveDisplaced - the transitions to be applied when
+        items are displaced by add, move, or remove operations, respectively (these override the
+        generic displaced transition if specified)
+     \endlist
+     For the \l Row, \l Column, \l Grid and \l Flow positioner elements, which operate with collections of child
+     items rather than data models, the following properties are used instead:
+     \list
+     \o \c add - the transition to apply to items that are created for the positioner, added to
+        or reparented to the positioner, or items that have become \l {Item::}{visible}
+     \o \c move - the transition to apply to items that have moved within the positioner, including
+        when they are displaced due to the addition or removal of other items, or when items are otherwise
+        rearranged within the positioner, or when items are repositioned due to the resizing of other
+        items in the positioner
+     \endlist
+     View transitions have access to a ViewTransition attached property that
+     provides details of the items that are under transition and the operation that triggered the
+     transition. Since view transitions are run once per item, these details can be used to customise
+     each transition for each individual item.
+     The ViewTransition attached property provides the following properties specific to the item to
+     which the transition is applied:
+     \list
+     \o ViewTransition.item - the item that is under transition
+     \o ViewTransition.index - the index of this item
+     \o ViewTransition.destination - the (x,y) point to which this item is moving for the relevant view operation
+     \endlist
+     In addition, ViewTransition provides properties specific to the items which are the target
+     of the operation that triggered the transition:
+     \list
+     \o ViewTransition.targetIndexes - the indexes of the target items
+     \o ViewTransition.targetItems - the target items themselves
+     \endlist
+     (Note that for the \l Row, \l Column, \l Grid and \l Flow positioner elements, the \c move transition only
+     provides these two additional details when the transition is triggered by the addition of items
+     to a positioner.)
+     View transitions can be written without referring to any of the attributes listed
+     above. These attributes merely provide extra details that are useful for customising view
+     transitions.
+     Following is an introduction to view transitions and the ways in which the ViewTransition
+     attached property can be used to augment view transitions.
+     \section2 View transitions: a simple example
+     Here is a basic example of the use of view transitions. The view below specifies transitions for
+     the \c add and \c displaced properties, which will be run when items are added to the view:
+     \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml 0
+     When the space key is pressed, adding an item to the model, the new item will fade in and
+     increase in scale over 400 milliseconds as it is added to the view. Also, any item that is
+     displaced by the addition of a new item will animate to its new position in the view over
+     400 milliseconds, as specified by the \c displaced transition.
+     If five items were inserted in succession at index 0, the effect would be this:
+     \image viewtransitions-basic.gif
+     Notice that the NumberAnimation objects above do not need to specify a \c target to animate
+     the appropriate item. Also, the NumberAnimation in the \c addTransition does not need to specify
+     the \c to value to move the item to its correct position in the view. This is because the view
+     implicitly sets the \c target and \c to values with the correct item and final item position
+     values if these properties are not explicitly defined.
+     At its simplest, a view transition may just animate an item to its new position following a
+     view operation, just as the \c displaced transition does above, or animate some item properties,
+     as in the \c add transition above. Additionally, a view transition may make use of the
+     ViewTransition attached property to customise animation behavior for different items. Following
+     are some examples of how this can be achieved.
+     \section2 Using the ViewTransition attached property
+     As stated, the various ViewTransition properties provide details specific to the individual item
+     being transitioned as well as the operation that triggered the transition. In the animation above,
+     five items are inserted in succession at index 0. When the fifth and final insertion takes place,
+     adding "Item 4" to the view, the \c add transition is run once (for the inserted item) and the
+     \c displaced transition is run four times (once for each of the four existing items in the view).
+     At this point, if we examined the \c displaced transition that was run for the bottom displaced
+     item ("Item 0"), the ViewTransition property values provided to this transition would be as follows:
+     \table
+     \header
+         \o Property
+         \o Value
+         \o Explanation
+     \row
+         \o ViewTransition.item
+         \o "Item 0" delegate instance
+         \o The "Item 0" \l Rectangle object itself
+     \row
+         \o ViewTransition.index
+         \o \c int value of 4
+         \o The index of "Item 0" within the model following the add operation
+     \row
+         \o ViewTransition.destination
+         \o \l point value of (0, 120)
+         \o The position that "Item 0" is moving to
+     \row
+         \o ViewTransition.targetIndexes
+         \o \c int array, just contains the integer "0" (zero)
+         \o The index of "Item 4", the new item added to the view
+     \row
+         \o ViewTransition.targetItems
+         \o object array, just contains the "Item 4" delegate instance
+         \o The "Item 4" \l Rectangle object - the new item added to the view
+     \endtable
+     The ViewTransition.targetIndexes and ViewTransition.targetItems lists provide the items and
+     indexes of all delegate instances that are the targets of the relevant operation. For an add
+     operation, these are all the items that are added into the view; for a remove, these are all
+     the items removed from the view, and so on. (Note these lists will only contain references to
+     items that have been created within the view or its cached items; targets that are not within
+     the visible area of the view or within the item cache will not be accessible.)
+     So, while the ViewTransition.item, ViewTransition.index and ViewTransition.destination values
+     vary for each individual transition that is run, the ViewTransition.targetIndexes and
+     ViewTransition.targetItems values are the same for every \c add and \c displaced transition
+     that is triggered by a particular add operation.
+     \section3 Delaying animations based on index
+     Since each view transition is run once for each item affected by the transition, the ViewTransition
+     properties can be used within a transition to define custom behavior for each item's transition.
+     For example, the ListView in the previous example could use this information to create a ripple-type
+     effect on the movement of the displaced items.
+     This can be achieved by modifying the \c displaced transition so that it delays the animation of
+     each displaced item based on the difference between its index (provided by ViewTransition.index)
+     and the first removed index (provided by ViewTransition.targetIndexes):
+     \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-delayedbyindex.qml 0
+     Each displaced item delays its animation by an additional 100 milliseconds, producing a subtle
+     ripple-type effect when items are displaced by the add, like this:
+     \image viewtransitions-delayedbyindex.gif
+     \section3 Animating items to intermediate positions
+     The ViewTransition.item property gives a reference to the item to which the transition is being
+     applied. This can be used to access any of the item's attributes, custom \c property values,
+     and so on.
+     Below is a modification of the \c displaced transition from the previous example. It adds a
+     ParallelAnimation with nested NumberAnimation objects that reference ViewTransition.item to access
+     each item's \c x and \c y values at the start of their transitions. This allows each item to
+     animate to an intermediate position relative to its starting point for the transition, before
+     animating to its final position in the view:
+     \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-intermediatemove.qml 0
+     Now, a displaced item will first move to a position of (20, 50) relative to its starting
+     position, and then to its final, correct position in the view:
+     \image viewtransitions-intermediatemove.gif
+     Since the final NumberAnimation does not specify a \c to value, the view implicitly sets this
+     value to the item's final position in the view, and so this last animation will move this item
+     to the correct place. If the transition requires the final position of the item for some calculation,
+     this is accessible through ViewTransition.destination.
+     Instead of using multiple NumberAnimations, you could use a PathAnimation to animate an item over
+     a curved path. For example, the \c add transition in the previous example could be augmented with
+     a PathAnimation as follows: to animate newly added items along a path:
+     \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-pathanim.qml 0
+     This animates newly added items along a path. Notice that each path is specified relative to
+     each item's final destination point, so that items inserted at different indexes start their
+     paths from different positions:
+     \image viewtransitions-pathanim.gif
+     \section2 Handling interrupted animations
+     A view transition may be interrupted at any time if a different view transition needs to be
+     applied while the original transition is in progress. For example, say Item A is inserted at index 0
+     and undergoes an "add" transition; then, Item B is inserted at index 0 in quick succession before
+     Item A's transition has finished. Since Item B is inserted before Item A, it will displace Item
+     A, causing the view to interrupt Item A's "add" transition mid-way and start a "displaced"
+     transition on Item A instead.
+     For simple animations that simply animate an item's movement to its final destination, this
+     interruption is unlikely to require additional consideration. However, if a transition changes other
+     properties, this interruption may cause unwanted side effects. Consider the first example on this
+     page, repeated below for convenience:
+     \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-basic.qml 0
+     If multiple items are added in rapid succession, without waiting for a previous transition
+     to finish, this is the result:
+     \image viewtransitions-interruptedbad.gif
+     Each newly added item undergoes an \c add transition, but before the transition can finish,
+     another item is added, displacing the previously added item. Because of this, the \c add
+     transition on the previously added item is interrupted and a \c displaced transition is
+     started on the item instead. Due to the interruption, the \c opacity and \c scale animations
+     have not completed, thus producing items with opacity and scale that are below 1.0.
+     To fix this, the \c displaced transition should additionally ensure the item properties are
+     set to the end values specified in the \c add transition, effectively resetting these values
+     whenever an item is displaced. In this case, it means setting the item opacity and scale to 1.0:
+     \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-interruptedgood.qml 0
+     Now, when an item's \c add transition is interrupted, its opacity and scale are animated to 1.0
+     upon displacement, avoiding the erroneous visual effects from before:
+     \image viewtransitions-interruptedgood.gif
+     The same principle applies to any combination of view transitions. An added item may be moved
+     before its add transition finishes, or a moved item may be removed before its moved transition
+     finishes, and so on; so, the rule of thumb is that every transition should handle the same set of
+     properties.
+     \section2 Restrictions regarding ScriptAction
+     When a view transition is initialized, any property bindings that refer to the ViewTransition
+     attached property are evaluated in preparation for the transition. Due to the nature of the
+     internal construction of a view transition, the attributes of the ViewTransition attached
+     property are only valid for the relevant item when the transition is initialized, and may not be
+     valid when the transition is actually run.
+     Therefore, a ScriptAction within a view transition should not refer to the ViewTransition
+     attached property, as it may not refer to the expected values at the time that the ScriptAction
+     is actually invoked. Consider the following example:
+     \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactionbad.qml 0
+     When the space key is pressed, three items are moved from index 5 to index 1. For each moved
+     item, the \c moveTransition sequence presumably animates the item's color to "yellow", then
+     animates it to its final position, then changes the item color back to "lightsteelblue" using a
+     ScriptAction. However, when run, the transition does not produce the intended result:
+     \image viewtransitions-scriptactionbad.gif
+     Only the last moved item is returned to the "lightsteelblue" color; the others remain yellow. This
+     is because the ScriptAction is not run until after the transition has already been initialized, by
+     which time the ViewTransition.item value has changed to refer to a different item; the item that
+     the script had intended to refer to is not the one held by ViewTransition.item at the time the
+     ScriptAction is actually invoked.
+     In this instance, to avoid this issue, the view could set the property using a PropertyAction
+     instead:
+     \snippet doc/src/snippets/declarative/viewtransitions/viewtransitions-scriptactiongood.qml 0
+     When the transition is initialized, the PropertyAction \c target will be set to the respective
+     ViewTransition.item for the transition and will later run with the correct item target as
+     expected.
+   */
+ /*!
+     \qmlattachedproperty list QtQuick2::ViewTransition::index
+     This attached property holds the index of the item that is being
+     transitioned.
+     Note that if the item is being moved, this property holds the index that
+     the item is moving to, not from.
+ */
+ /*!
+     \qmlattachedproperty list QtQuick2::ViewTransition::item
+     This attached property holds the the item that is being transitioned.
+     \warning This item should not be kept and referred to outside of the transition
+     as it may become invalid as the view changes.
+ */
+ /*!
+     \qmlattachedproperty list QtQuick2::ViewTransition::destination
+     This attached property holds the final destination position for the transitioned
+     item within the view.
+     This property value is a \l point with \c x and \c y properties.
+ */
+ /*!
+     \qmlattachedproperty list QtQuick2::ViewTransition::targetIndexes
+     This attached property holds a list of the indexes of the items in view
+     that are the target of the relevant operation.
+     The targets are the items that are the subject of the operation. For
+     an add operation, these are the items being added; for a remove, these
+     are the items being removed; for a move, these are the items being
+     moved.
+     For example, if the transition was triggered by an insert operation
+     that added two items at index 1 and 2, this targetIndexes list would
+     have the value [1,2].
+     \note The targetIndexes list only contains the indexes of items that are actually
+     in view, or will be in the view once the relevant operation completes.
+     \sa QtQuick2::ViewTransition::targetIndexes
+ */
+ /*!
+     \qmlattachedproperty list QtQuick2::ViewTransition::targetItems
+     This attached property holds the list of items in view that are the
+     target of the relevant operation.
+     The targets are the items that are the subject of the operation. For
+     an add operation, these are the items being added; for a remove, these
+     are the items being removed; for a move, these are the items being
+     moved.
+     For example, if the transition was triggered by an insert operation
+     that added two items at index 1 and 2, this targetItems list would
+     contain these two items.
+     \note The targetItems list only contains items that are actually
+     in view, or will be in the view once the relevant operation completes.
+     \warning The objects in this list should not be kept and referred to
+     outside of the transition as the items may become invalid. The targetItems
+     are only valid when the Transition is initially created; this also means
+     they should not be used by ScriptAction objects in the Transition, which are
+     not evaluated until the transition is run.
+     \sa QtQuick2::ViewTransition::targetIndexes
+ */
 -    return QDeclarativeListProperty<QObject>(this, m_targetItems);
++QQmlListProperty<QObject> QQuickViewTransitionAttached::targetItems()
+ {
++    return QQmlListProperty<QObject>(this, m_targetItems);
+ }
+ QQuickViewTransitionAttached *QQuickViewTransitionAttached::qmlAttachedProperties(QObject *obj)
+ {
+     return new QQuickViewTransitionAttached(obj);
+ }
+ QT_END_NAMESPACE
index 0000000,57ea85b..3fb43d6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,209 +1,209 @@@
 -** This file is part of the QtDeclarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
 -#include <private/qdeclarativetransitionmanager_p_p.h>
++** This file is part of the QtQml module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #ifndef QQUICKITEMVIEWTRANSITION_P_P_H
+ #define QQUICKITEMVIEWTRANSITION_P_P_H
 -QT_MODULE(Declarative)
++#include <private/qquicktransitionmanager_p_p.h>
+ QT_BEGIN_HEADER
+ QT_BEGIN_NAMESPACE
 -    QDeclarativeTransition *transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget);
++QT_MODULE(Quick)
+ class QQuickItem;
+ class QQuickViewItem;
+ class QQuickItemViewTransitionJob;
+ class QQuickItemViewTransitionChangeListener
+ {
+ public:
+     QQuickItemViewTransitionChangeListener() {}
+     virtual ~QQuickItemViewTransitionChangeListener() {}
+     virtual void viewItemTransitionFinished(QQuickViewItem *item) = 0;
+ };
+ class QQuickItemViewTransitioner
+ {
+ public:
+     enum TransitionType {
+         NoTransition,
+         PopulateTransition,
+         AddTransition,
+         MoveTransition,
+         RemoveTransition
+     };
+     QQuickItemViewTransitioner();
+     virtual ~QQuickItemViewTransitioner();
+     bool canTransition(QQuickItemViewTransitioner::TransitionType type, bool asTarget) const;
+     void transitionNextReposition(QQuickViewItem *item, QQuickItemViewTransitioner::TransitionType type, bool isTarget);
 -    QDeclarativeTransition *populateTransition;
 -    QDeclarativeTransition *addTransition;
 -    QDeclarativeTransition *addDisplacedTransition;
 -    QDeclarativeTransition *moveTransition;
 -    QDeclarativeTransition *moveDisplacedTransition;
 -    QDeclarativeTransition *removeTransition;
 -    QDeclarativeTransition *removeDisplacedTransition;
 -    QDeclarativeTransition *displacedTransition;
++    QQuickTransition *transitionObject(QQuickItemViewTransitioner::TransitionType type, bool asTarget);
+     const QList<int> &targetIndexes(QQuickItemViewTransitioner::TransitionType type) const;
+     const QList<QObject *> &targetItems(QQuickItemViewTransitioner::TransitionType type) const;
+     inline void setPopulateTransitionEnabled(bool b) { usePopulateTransition = b; }
+     inline void setChangeListener(QQuickItemViewTransitionChangeListener *obj) { changeListener = obj; }
+     QSet<QQuickItemViewTransitionJob *> runningJobs;
+     QList<int> addTransitionIndexes;
+     QList<int> moveTransitionIndexes;
+     QList<int> removeTransitionIndexes;
+     QList<QObject *> addTransitionTargets;
+     QList<QObject *> moveTransitionTargets;
+     QList<QObject *> removeTransitionTargets;
 -    Q_PROPERTY(QDeclarativeListProperty<QObject> targetItems READ targetItems NOTIFY targetItemsChanged)
++    QQuickTransition *populateTransition;
++    QQuickTransition *addTransition;
++    QQuickTransition *addDisplacedTransition;
++    QQuickTransition *moveTransition;
++    QQuickTransition *moveDisplacedTransition;
++    QQuickTransition *removeTransition;
++    QQuickTransition *removeDisplacedTransition;
++    QQuickTransition *displacedTransition;
+ private:
+     friend class QQuickItemViewTransitionJob;
+     QQuickItemViewTransitionChangeListener *changeListener;
+     bool usePopulateTransition;
+     void finishedTransition(QQuickItemViewTransitionJob *job, QQuickViewItem *item);
+ };
+ /*
+   An item in a view, that can be transitioned using QQuickViewTransitionJob.
+   */
+ class QQuickViewItem
+ {
+ public:
+     QQuickViewItem(QQuickItem *i);
+     virtual ~QQuickViewItem();
+     qreal itemX() const;
+     qreal itemY() const;
+     void moveTo(const QPointF &pos);
+     void setVisible(bool visible);
+     bool transitionScheduledOrRunning() const;
+     bool transitionRunning() const;
+     bool isPendingRemoval() const;
+     bool prepareTransition(const QRectF &viewBounds);
+     void startTransition(QQuickItemViewTransitioner *transitioner);
+     void stopTransition();
+     QPointF nextTransitionTo;
+     QQuickItem *item;
+     QQuickItemViewTransitionJob *transition;
+     QQuickItemViewTransitioner::TransitionType nextTransitionType;
+     int index;
+     bool isTransitionTarget;
+     bool nextTransitionToSet;
+ private:
+     friend class QQuickItemViewTransitioner;
+     friend class QQuickItemViewTransitionJob;
+     void setNextTransition(QQuickItemViewTransitioner::TransitionType, bool isTargetItem);
+     bool transitionWillChangePosition() const;
+     void finishedTransition();
+     void resetTransitionData();
+ };
+ class QQuickViewTransitionAttached : public QObject
+ {
+     Q_OBJECT
+     Q_PROPERTY(int index READ index NOTIFY indexChanged)
+     Q_PROPERTY(QQuickItem* item READ item NOTIFY itemChanged)
+     Q_PROPERTY(QPointF destination READ destination NOTIFY destinationChanged)
+     Q_PROPERTY(QList<int> targetIndexes READ targetIndexes NOTIFY targetIndexesChanged)
 -    QDeclarativeListProperty<QObject> targetItems();
++    Q_PROPERTY(QQmlListProperty<QObject> targetItems READ targetItems NOTIFY targetItemsChanged)
+ public:
+     QQuickViewTransitionAttached(QObject *parent);
+     int index() const { return m_index; }
+     QQuickItem *item() const { return m_item; }
+     QPointF destination() const { return m_destination; }
+     QList<int> targetIndexes() const { return m_targetIndexes; }
++    QQmlListProperty<QObject> targetItems();
+     static QQuickViewTransitionAttached *qmlAttachedProperties(QObject *);
+ signals:
+     void indexChanged();
+     void itemChanged();
+     void destinationChanged();
+     void targetIndexesChanged();
+     void targetItemsChanged();
+ private:
+     friend class QQuickItemViewTransitionJob;
+     QPointF m_destination;
+     QList<int> m_targetIndexes;
+     QList<QObject *> m_targetItems;
+     QQuickItem *m_item;
+     int m_index;
+ };
+ QT_END_NAMESPACE
+ QML_DECLARE_TYPE(QQuickViewTransitionAttached)
+ QML_DECLARE_TYPEINFO(QQuickViewTransitionAttached, QML_HAS_ATTACHED_PROPERTIES)
+ QT_END_HEADER
+ #endif // QQUICKITEMVIEWTRANSITION_P_P_H
@@@ -944,18 -955,18 +955,18 @@@ void QQuickListViewPrivate::updateInlin
      if (listItem->attached->m_prevSection != listItem->attached->m_section
              && (sectionCriteria->labelPositioning() & QQuickViewSection::InlineLabels
                  || (listItem->index == 0 && sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart))) {
-         if (!listItem->section) {
+         if (!listItem->section()) {
              qreal pos = listItem->position();
-             listItem->section = getSectionItem(listItem->attached->m_section);
+             listItem->setSection(getSectionItem(listItem->attached->m_section));
              listItem->setPosition(pos);
          } else {
-             QQmlContext *context = QQmlEngine::contextForObject(listItem->section)->parentContext();
 -            QDeclarativeContext *context = QDeclarativeEngine::contextForObject(listItem->section())->parentContext();
++            QQmlContext *context = QQmlEngine::contextForObject(listItem->section())->parentContext();
              context->setContextProperty(QLatin1String("section"), listItem->attached->m_section);
          }
-     } else if (listItem->section) {
+     } else if (listItem->section()) {
          qreal pos = listItem->position();
-         releaseSectionItem(listItem->section);
-         listItem->section = 0;
+         releaseSectionItem(listItem->section());
+         listItem->setSection(0);
          listItem->setPosition(pos);
      }
  }
@@@ -197,7 -197,8 +197,8 @@@ Q_SIGNALS
      void viewChanged();
  
  public:
 -    QDeclarativeGuard<QQuickListView> m_view;
 +    QQmlGuard<QQuickListView> m_view;
+     QQuickItem *m_sectionItem;
  };
  
  
@@@ -137,34 -140,39 +140,39 @@@ void QQuickBasePositioner::setSpacing(q
      emit spacingChanged();
  }
  
 -QDeclarativeTransition *QQuickBasePositioner::move() const
 +QQuickTransition *QQuickBasePositioner::move() const
  {
      Q_D(const QQuickBasePositioner);
-     return d->moveTransition;
+     return d->transitioner ? d->transitioner->displacedTransition : 0;
  }
  
 -void QQuickBasePositioner::setMove(QDeclarativeTransition *mt)
 +void QQuickBasePositioner::setMove(QQuickTransition *mt)
  {
      Q_D(QQuickBasePositioner);
-     if (mt == d->moveTransition)
+     if (!d->transitioner)
+         d->transitioner = new QQuickItemViewTransitioner;
+     if (mt == d->transitioner->displacedTransition)
          return;
-     d->moveTransition = mt;
+     d->transitioner->displacedTransition = mt;
      emit moveChanged();
  }
  
 -QDeclarativeTransition *QQuickBasePositioner::add() const
 +QQuickTransition *QQuickBasePositioner::add() const
  {
      Q_D(const QQuickBasePositioner);
-     return d->addTransition;
+     return d->transitioner ? d->transitioner->addTransition : 0;
  }
  
 -void QQuickBasePositioner::setAdd(QDeclarativeTransition *add)
 +void QQuickBasePositioner::setAdd(QQuickTransition *add)
  {
      Q_D(QQuickBasePositioner);
-     if (add == d->addTransition)
+     if (!d->transitioner)
+         d->transitioner = new QQuickItemViewTransitioner;
+     if (add == d->transitioner->addTransition)
          return;
  
-     d->addTransition = add;
+     d->transitioner->addTransition = add;
      emit addChanged();
  }
  
@@@ -511,15 -557,24 +557,24 @@@ void QQuickPositionerAttached::setIsLas
  /*!
      \qmlproperty Transition QtQuick2::Column::move
  
-     This property holds the transition to apply to any item that has moved
-     within the positioner. Positioner transitions will only affect
-     the position (x, y) of items.
+     This property holds the transition to run for items that have moved within the
+     positioner. For a positioner, this applies to:
+     \list
+     \o Child items that move when they are displaced due to the addition, removal or
+        rearrangement of other items in the positioner
+     \o Child items that are repositioned due to the resizing of other items in the positioner
+     \endlist
+     The transition can use the \l ViewTransition property to access more details about
+     the item that is being moved. Note, however, that for this move transition, the
+     ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when
+     this transition is triggered by the addition of other items in the positioner; in other
+     cases, these lists will be empty.
  
-     This transition is applied to items that are displaced as a result of the
-     addition or removal of other items in the positioner, or when items move due to
-     a move operation in a related model, or when items resize themselves.
+     See the \l ViewTransition documentation for more details and examples on using these transitions.
  
-     \sa add, {qml/positioners}{Positioners example}
 -    \sa add, ViewTransition, {declarative/positioners}{Positioners example}
++    \sa add, ViewTransition, {qml/positioners}{Positioners example}
  */
  /*!
    \qmlproperty real QtQuick2::Column::spacing
@@@ -635,27 -690,24 +690,24 @@@ void QQuickColumn::reportConflictingAnc
  /*!
      \qmlproperty Transition QtQuick2::Row::move
  
-     This property holds the transition to apply to any item that has moved
-     within the positioner. Positioner transitions will only affect
-     the position (x, y) of items.
-     This transition is applied to items that are displaced as a result of the
-     addition or removal of other items in the positioner, or when items move due to
-     a move operation in a related model, or when items resize themselves.
-     \qml
-     Row {
-         id: positioner
-         move: Transition {
-             NumberAnimation {
-                 properties: "x"
-                 duration: 1000
-             }
-         }
-     }
-     \endqml
+     This property holds the transition to run for items that have moved within the
+     positioner. For a positioner, this applies to:
+     \list
+     \o Child items that move when they are displaced due to the addition, removal or
+        rearrangement of other items in the positioner
+     \o Child items that are repositioned due to the resizing of other items in the positioner
+     \endlist
  
-     \sa add, {qml/positioners}{Positioners example}
+     The transition can use the \l ViewTransition property to access more details about
+     the item that is being moved. Note, however, that for this move transition, the
+     ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when
+     this transition is triggered by the addition of other items in the positioner; in other
+     cases, these lists will be empty.
+     See the \l ViewTransition documentation for more details and examples on using these transitions.
 -    \sa add, ViewTransition, {declarative/positioners}{Positioners example}
++    \sa add, ViewTransition, {qml/positioners}{Positioners example}
  */
  /*!
    \qmlproperty real QtQuick2::Row::spacing
@@@ -849,26 -902,24 +902,24 @@@ void QQuickRow::reportConflictingAnchor
  /*!
      \qmlproperty Transition QtQuick2::Grid::move
  
-     This property holds the transition to apply to any item that has moved
-     within the positioner. Positioner transitions will only affect
-     the position (x, y) of items.
+     This property holds the transition to run for items that have moved within the
+     positioner. For a positioner, this applies to:
  
-     This transition is applied to items that are displaced as a result of the
-     addition or removal of other items in the positioner, or when items move due to
-     a move operation in a related model, or when items resize themselves.
+     \list
+     \o Child items that move when they are displaced due to the addition, removal or
+        rearrangement of other items in the positioner
+     \o Child items that are repositioned due to the resizing of other items in the positioner
+     \endlist
  
-     \qml
-     Grid {
-         move: Transition {
-             NumberAnimation {
-                 properties: "x,y"
-                 duration: 1000
-             }
-         }
-     }
-     \endqml
+     The transition can use the \l ViewTransition property to access more details about
+     the item that is being moved. Note, however, that for this move transition, the
+     ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when
+     this transition is triggered by the addition of other items in the positioner; in other
+     cases, these lists will be empty.
+     See the \l ViewTransition documentation for more details and examples on using these transitions.
  
-     \sa add, {qml/positioners}{Positioners example}
 -    \sa add, ViewTransition, {declarative/positioners}{Positioners example}
++    \sa add, ViewTransition, {qml/positioners}{Positioners example}
  */
  /*!
    \qmlproperty qreal QtQuick2::Grid::spacing
@@@ -1264,27 -1315,24 +1315,24 @@@ void QQuickGrid::reportConflictingAncho
  /*!
      \qmlproperty Transition QtQuick2::Flow::move
  
-     This property holds the transition to apply to any item that has moved
-     within the positioner. Positioner transitions will only affect
-     the position (x, y) of items.
-     This transition is applied to items that are displaced as a result of the
-     addition or removal of other items in the positioner, or when items move due to
-     a move operation in a related model, or when items resize themselves.
-     \qml
-     Flow {
-         id: positioner
-         move: Transition {
-             NumberAnimation {
-                 properties: "x,y"
-                 ease: "easeOutBounce"
-             }
-         }
-     }
-     \endqml
+     This property holds the transition to run for items that have moved within the
+     positioner. For a positioner, this applies to:
+     \list
+     \o Child items that move when they are displaced due to the addition, removal or
+        rearrangement of other items in the positioner
+     \o Child items that are repositioned due to the resizing of other items in the positioner
+     \endlist
+     The transition can use the \l ViewTransition property to access more details about
+     the item that is being moved. Note, however, that for this move transition, the
+     ViewTransition.targetIndexes and ViewTransition.targetItems lists are only set when
+     this transition is triggered by the addition of other items in the positioner; in other
+     cases, these lists will be empty.
+     See the \l ViewTransition documentation for more details and examples on using these transitions.
  
-     \sa add, {qml/positioners}{Positioners example}
 -    \sa add, ViewTransition, {declarative/positioners}{Positioners example}
++    \sa add, ViewTransition, {qml/positioners}{Positioners example}
  */
  /*!
    \qmlproperty real QtQuick2::Flow::spacing
@@@ -43,8 -43,9 +43,9 @@@
  #define QQUICKPOSITIONERS_P_H
  
  #include "qquickimplicitsizeitem_p.h"
+ #include "qquickitemviewtransition_p.h"
  
 -#include <QtQuick/private/qdeclarativestate_p.h>
 +#include <QtQuick/private/qquickstate_p.h>
  #include <private/qpodvector_p.h>
  
  #include <QtCore/qobject.h>
@@@ -92,10 -93,11 +93,11 @@@ class Q_QUICK_PRIVATE_EXPORT QQuickBase
      Q_OBJECT
  
      Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
 -    Q_PROPERTY(QDeclarativeTransition *move READ move WRITE setMove NOTIFY moveChanged)
 -    Q_PROPERTY(QDeclarativeTransition *add READ add WRITE setAdd NOTIFY addChanged)
 +    Q_PROPERTY(QQuickTransition *move READ move WRITE setMove NOTIFY moveChanged)
 +    Q_PROPERTY(QQuickTransition *add READ add WRITE setAdd NOTIFY addChanged)
  public:
      enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 };
      QQuickBasePositioner(PositionerType, QQuickItem *parent);
      ~QQuickBasePositioner();
  
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
  #include <QObject>
  #include <QUrl>
  #include <QVariantMap>
 -#include <QDeclarativeListProperty>
 -#include <QtQuick/private/qdeclarativepixmapcache_p.h>
 +#include <QQmlListProperty>
 +#include <QtQuick/private/qquickpixmapcache_p.h>
  #include "qquickspriteengine_p.h"
+ #include <QDebug>
  
  QT_BEGIN_HEADER
  
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
index 0000000,a3a8a6e..ce0a246
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,482 +1,482 @@@
 -** This file is part of the Declarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
 -#include <QtDeclarative/qdeclarativeinfo.h>
++** This file is part of the QtQuick module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #include "qquickspritesequence_p.h"
+ #include "qquicksprite_p.h"
+ #include "qquickspriteengine_p.h"
+ #include <QtQuick/private/qsgcontext_p.h>
+ #include <private/qsgadaptationlayer_p.h>
+ #include <QtQuick/qsgnode.h>
+ #include <QtQuick/qsgengine.h>
+ #include <QtQuick/qsgtexturematerial.h>
+ #include <QtQuick/qsgtexture.h>
+ #include <QtQuick/qquickcanvas.h>
 -QDeclarativeListProperty<QQuickSprite> QQuickSpriteSequence::sprites()
++#include <QtQml/qqmlinfo.h>
+ #include <QFile>
+ #include <cmath>
+ #include <qmath.h>
+ #include <QDebug>
+ QT_BEGIN_NAMESPACE
+ static const char vertexShaderCode[] =
+     "attribute highp vec2 vTex;\n"
+     "uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress\n"
+     "uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation)\n"
+     "uniform highp vec2 size;//w,h of element\n"
+     "\n"
+     "uniform highp mat4 qt_Matrix;\n"
+     "\n"
+     "varying highp vec4 fTexS;\n"
+     "varying lowp float progress;\n"
+     "\n"
+     "\n"
+     "void main() {\n"
+     "    progress = animData.z;\n"
+     "    //Calculate frame location in texture\n"
+     "    fTexS.xy = animPos.xy + vTex.xy * animData.xy;\n"
+     "    //Next frame is also passed, for interpolation\n"
+     "    fTexS.zw = animPos.zw + vTex.xy * animData.xy;\n"
+     "\n"
+     "    gl_Position = qt_Matrix * vec4(size.x * vTex.x, size.y * vTex.y, 0, 1);\n"
+     "}\n";
+ static const char fragmentShaderCode[] =
+     "uniform sampler2D texture;\n"
+     "uniform lowp float qt_Opacity;\n"
+     "\n"
+     "varying highp vec4 fTexS;\n"
+     "varying lowp float progress;\n"
+     "\n"
+     "void main() {\n"
+     "    gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), progress) * qt_Opacity;\n"
+     "}\n";
+ class QQuickSpriteSequenceMaterial : public QSGMaterial
+ {
+ public:
+     QQuickSpriteSequenceMaterial();
+     ~QQuickSpriteSequenceMaterial();
+     virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
+     virtual QSGMaterialShader *createShader() const;
+     virtual int compare(const QSGMaterial *other) const
+     {
+         return this - static_cast<const QQuickSpriteSequenceMaterial *>(other);
+     }
+     QSGTexture *texture;
+     float animT;
+     float animX1;
+     float animY1;
+     float animX2;
+     float animY2;
+     float animW;
+     float animH;
+     float elementWidth;
+     float elementHeight;
+ };
+ QQuickSpriteSequenceMaterial::QQuickSpriteSequenceMaterial()
+     : animT(0.0f)
+     , animX1(0.0f)
+     , animY1(0.0f)
+     , animX2(0.0f)
+     , animY2(0.0f)
+     , animW(1.0f)
+     , animH(1.0f)
+     , elementWidth(1.0f)
+     , elementHeight(1.0f)
+ {
+     setFlag(Blending, true);
+ }
+ QQuickSpriteSequenceMaterial::~QQuickSpriteSequenceMaterial()
+ {
+     delete texture;
+ }
+ class SpriteSequenceMaterialData : public QSGMaterialShader
+ {
+ public:
+     SpriteSequenceMaterialData(const char * /* vertexFile */ = 0, const char * /* fragmentFile */ = 0)
+     {
+     }
+     void deactivate() {
+         QSGMaterialShader::deactivate();
+         for (int i=0; i<8; ++i) {
+             program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
+         }
+     }
+     virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
+     {
+         QQuickSpriteSequenceMaterial *m = static_cast<QQuickSpriteSequenceMaterial *>(newEffect);
+         m->texture->bind();
+         program()->setUniformValue(m_opacity_id, state.opacity());
+         program()->setUniformValue(m_animData_id, m->animW, m->animH, m->animT);
+         program()->setUniformValue(m_animPos_id, m->animX1, m->animY1, m->animX2, m->animY2);
+         program()->setUniformValue(m_size_id, m->elementWidth, m->elementHeight);
+         if (state.isMatrixDirty())
+             program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+     }
+     virtual void initialize() {
+         m_matrix_id = program()->uniformLocation("qt_Matrix");
+         m_opacity_id = program()->uniformLocation("qt_Opacity");
+         m_animData_id = program()->uniformLocation("animData");
+         m_animPos_id = program()->uniformLocation("animPos");
+         m_size_id = program()->uniformLocation("size");
+     }
+     virtual const char *vertexShader() const { return vertexShaderCode; }
+     virtual const char *fragmentShader() const { return fragmentShaderCode; }
+     virtual char const *const *attributeNames() const {
+         static const char *attr[] = {
+            "vTex",
+             0
+         };
+         return attr;
+     }
+     int m_matrix_id;
+     int m_opacity_id;
+     int m_animData_id;
+     int m_animPos_id;
+     int m_size_id;
+     static float chunkOfBytes[1024];
+ };
+ float SpriteSequenceMaterialData::chunkOfBytes[1024];
+ QSGMaterialShader *QQuickSpriteSequenceMaterial::createShader() const
+ {
+     return new SpriteSequenceMaterialData;
+ }
+ struct SpriteVertex {
+     float tx;
+     float ty;
+ };
+ struct SpriteVertices {
+     SpriteVertex v1;
+     SpriteVertex v2;
+     SpriteVertex v3;
+     SpriteVertex v4;
+ };
+ /*!
+     \qmlclass SpriteSequence QQuickSpriteSequence
+     \inqmlmodule QtQuick 2
+     \inherits Item
+     \brief The SpriteSequence element draws a sprite animation
+ */
+ /*!
+     \qmlproperty bool QtQuick2::SpriteSequence::running
+     Whether the sprite is animating or not.
+     Default is true
+ */
+ /*!
+     \qmlproperty bool QtQuick2::SpriteSequence::interpolate
+     If true, interpolation will occur between sprite frames to make the
+     animation appear smoother.
+     Default is true.
+ */
+ /*!
+     \qmlproperty string QtQuick2::SpriteSequence::goalSprite
+     The name of the Sprite which is currently animating.
+ */
+ /*!
+     \qmlproperty string QtQuick2::SpriteSequence::goalSprite
+     The name of the Sprite which the animation should move to.
+     Sprite states have defined durations and transitions between them, setting goalState
+     will cause it to disregard any path weightings (including 0) and head down the path
+     which will reach the goalState quickest (fewest animations). It will pass through
+     intermediate states on that path, and animate them for their duration.
+     If it is possible to return to the goalState from the starting point of the goalState
+     it will continue to do so until goalState is set to "" or an unreachable state.
+ */
+ /*! \qmlmethod void QtQuick2::SpriteSequence::jumpTo(string sprite)
+     This function causes the sprite to jump to the specified state immediately, intermediate
+     states are not played.
+ */
+ /*!
+     \qmlproperty list<Sprite> QtQuick2::SpriteSequence::sprites
+     The sprite or sprites to draw. Sprites will be scaled to the size of this element.
+ */
+ //TODO: Implicitly size element to size of first sprite?
+ QQuickSpriteSequence::QQuickSpriteSequence(QQuickItem *parent) :
+     QQuickItem(parent)
+     , m_node(0)
+     , m_material(0)
+     , m_spriteEngine(0)
+     , m_curFrame(0)
+     , m_pleaseReset(false)
+     , m_running(true)
+     , m_interpolate(true)
+     , m_curStateIdx(0)
+ {
+     setFlag(ItemHasContents);
+     connect(this, SIGNAL(runningChanged(bool)),
+             this, SLOT(update()));
+ }
+ void QQuickSpriteSequence::jumpTo(const QString &sprite)
+ {
+     if (!m_spriteEngine)
+         return;
+     m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite), 0, true);
+ }
+ void QQuickSpriteSequence::setGoalSprite(const QString &sprite)
+ {
+     if (m_goalState != sprite){
+         m_goalState = sprite;
+         emit goalSpriteChanged(sprite);
+         m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite));
+     }
+ }
 -    return QDeclarativeListProperty<QQuickSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear);
++QQmlListProperty<QQuickSprite> QQuickSpriteSequence::sprites()
+ {
 -    } else if (m_spriteEngine->status() == QDeclarativePixmap::Null) {
++    return QQmlListProperty<QQuickSprite>(this, &m_sprites, spriteAppend, spriteCount, spriteAt, spriteClear);
+ }
+ void QQuickSpriteSequence::createEngine()
+ {
+     //TODO: delay until component complete
+     if (m_spriteEngine)
+         delete m_spriteEngine;
+     if (m_sprites.count())
+         m_spriteEngine = new QQuickSpriteEngine(m_sprites, this);
+     else
+         m_spriteEngine = 0;
+     reset();
+ }
+ static QSGGeometry::Attribute SpriteSequence_Attributes[] = {
+     QSGGeometry::Attribute::create(0, 2, GL_FLOAT),         // tex
+ };
+ static QSGGeometry::AttributeSet SpriteSequence_AttributeSet =
+ {
+     1, // Attribute Count
+     2 * sizeof(float),
+     SpriteSequence_Attributes
+ };
+ QSGGeometryNode* QQuickSpriteSequence::buildNode()
+ {
+     if (!m_spriteEngine) {
+         qmlInfo(this) << "No sprite engine...";
+         return 0;
 -    } else if (m_spriteEngine->status() == QDeclarativePixmap::Loading) {
++    } else if (m_spriteEngine->status() == QQuickPixmap::Null) {
+         m_spriteEngine->startAssemblingImage();
+         update();//Schedule another update, where we will check again
+         return 0;
++    } else if (m_spriteEngine->status() == QQuickPixmap::Loading) {
+         update();//Schedule another update, where we will check again
+         return 0;
+     }
+     m_material = new QQuickSpriteSequenceMaterial();
+     QImage image = m_spriteEngine->assembledImage();
+     if (image.isNull())
+         return 0;
+     m_sheetSize = QSizeF(image.size());
+     m_material->texture = canvas()->createTextureFromImage(image);
+     m_material->texture->setFiltering(QSGTexture::Linear);
+     m_spriteEngine->start(0);
+     m_material->animT = 0;
+     m_material->animX1 = m_spriteEngine->spriteX() / m_sheetSize.width();
+     m_material->animY1 = m_spriteEngine->spriteY() / m_sheetSize.height();
+     m_material->animX2 = m_material->animX1;
+     m_material->animY2 = m_material->animY1;
+     m_material->animW = m_spriteEngine->spriteWidth() / m_sheetSize.width();
+     m_material->animH = m_spriteEngine->spriteHeight() / m_sheetSize.height();
+     m_material->elementWidth = width();
+     m_material->elementHeight = height();
+     m_curState = m_spriteEngine->state(m_spriteEngine->curState())->name();
+     emit currentSpriteChanged(m_curState);
+     int vCount = 4;
+     int iCount = 6;
+     QSGGeometry *g = new QSGGeometry(SpriteSequence_AttributeSet, vCount, iCount);
+     g->setDrawingMode(GL_TRIANGLES);
+     SpriteVertices *p = (SpriteVertices *) g->vertexData();
+     p->v1.tx = 0;
+     p->v1.ty = 0;
+     p->v2.tx = 1.0;
+     p->v2.ty = 0;
+     p->v3.tx = 0;
+     p->v3.ty = 1.0;
+     p->v4.tx = 1.0;
+     p->v4.ty = 1.0;
+     quint16 *indices = g->indexDataAsUShort();
+     indices[0] = 0;
+     indices[1] = 1;
+     indices[2] = 2;
+     indices[3] = 1;
+     indices[4] = 3;
+     indices[5] = 2;
+     m_timestamp.start();
+     m_node = new QSGGeometryNode();
+     m_node->setGeometry(g);
+     m_node->setMaterial(m_material);
+     m_node->setFlag(QSGGeometryNode::OwnsMaterial);
+     return m_node;
+ }
+ void QQuickSpriteSequence::reset()
+ {
+     m_pleaseReset = true;
+ }
+ QSGNode *QQuickSpriteSequence::updatePaintNode(QSGNode *, UpdatePaintNodeData *)
+ {
+     if (m_pleaseReset) {
+         delete m_node;
+         m_node = 0;
+         m_material = 0;
+         m_pleaseReset = false;
+     }
+     prepareNextFrame();
+     if (m_running) {
+         update();
+         if (m_node)
+             m_node->markDirty(QSGNode::DirtyMaterial);
+     }
+     return m_node;
+ }
+ void QQuickSpriteSequence::prepareNextFrame()
+ {
+     if (m_node == 0)
+         m_node = buildNode();
+     if (m_node == 0) //error creating node
+         return;
+     uint timeInt = m_timestamp.elapsed();
+     qreal time =  timeInt / 1000.;
+     m_material->elementHeight = height();
+     m_material->elementWidth = width();
+     //Advance State
+     m_spriteEngine->updateSprites(timeInt);
+     if (m_curStateIdx != m_spriteEngine->curState()) {
+         m_curStateIdx = m_spriteEngine->curState();
+         m_curState = m_spriteEngine->state(m_spriteEngine->curState())->name();
+         emit currentSpriteChanged(m_curState);
+         m_curFrame= -1;
+     }
+     //Advance Sprite
+     qreal animT = m_spriteEngine->spriteStart()/1000.0;
+     qreal frameCount = m_spriteEngine->spriteFrames();
+     qreal frameDuration = m_spriteEngine->spriteDuration()/frameCount;
+     double frameAt;
+     qreal progress;
+     if (frameDuration > 0) {
+         qreal frame = (time - animT)/(frameDuration / 1000.0);
+         frame = qBound(qreal(0.0), frame, frameCount - qreal(1.0));//Stop at count-1 frames until we have between anim interpolation
+         progress = modf(frame,&frameAt);
+     } else {
+         m_curFrame++;
+         if (m_curFrame >= frameCount){
+             m_curFrame = 0;
+             m_spriteEngine->advance();
+         }
+         frameAt = m_curFrame;
+         progress = 0;
+     }
+     if (m_spriteEngine->sprite()->reverse())
+         frameAt = (m_spriteEngine->spriteFrames() - 1) - frameAt;
+     qreal y = m_spriteEngine->spriteY() / m_sheetSize.height();
+     qreal w = m_spriteEngine->spriteWidth() / m_sheetSize.width();
+     qreal h = m_spriteEngine->spriteHeight() / m_sheetSize.height();
+     qreal x1 = m_spriteEngine->spriteX() / m_sheetSize.width();
+     x1 += frameAt * w;
+     qreal x2 = x1;
+     if (frameAt < (frameCount-1))
+         x2 += w;
+     m_material->animX1 = x1;
+     m_material->animY1 = y;
+     m_material->animX2 = x2;
+     m_material->animY2 = y;
+     m_material->animW = w;
+     m_material->animH = h;
+     m_material->animT = m_interpolate ? progress : 0.0;
+ }
+ QT_END_NAMESPACE
index 0000000,8a95594..a2f9e41
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,148 +1,148 @@@
 -** This file is part of the Declarative module of the Qt Toolkit.
+ /****************************************************************************
+ **
+ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/
+ **
 -    Q_PROPERTY(QDeclarativeListProperty<QQuickSprite> sprites READ sprites)
++** This file is part of the QtQuick module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** This file may be used under the terms of the GNU Lesser General Public
+ ** License version 2.1 as published by the Free Software Foundation and
+ ** appearing in the file LICENSE.LGPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU Lesser
+ ** General Public License version 2.1 requirements will be met:
+ ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain additional
+ ** rights. These rights are described in the Nokia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+ #ifndef QQUICKSPRITESEQUENCE_P_H
+ #define QQUICKSPRITESEQUENCE_P_H
+ #include <QtQuick/QQuickItem>
+ #include <QTime>
+ QT_BEGIN_HEADER
+ QT_BEGIN_NAMESPACE
+ class QSGContext;
+ class QQuickSprite;
+ class QQuickSpriteEngine;
+ class QSGGeometryNode;
+ class QQuickSpriteSequenceMaterial;
+ class Q_AUTOTEST_EXPORT QQuickSpriteSequence : public QQuickItem
+ {
+     Q_OBJECT
+     Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
+     Q_PROPERTY(bool interpolate READ interpolate WRITE setInterpolate NOTIFY interpolateChanged)
+     Q_PROPERTY(QString goalSprite READ goalSprite WRITE setGoalSprite NOTIFY goalSpriteChanged)
+     Q_PROPERTY(QString currentSprite READ currentSprite NOTIFY currentSpriteChanged)
+     //###try to share similar spriteEngines for less overhead?
 -    QDeclarativeListProperty<QQuickSprite> sprites();
++    Q_PROPERTY(QQmlListProperty<QQuickSprite> sprites READ sprites)
+     Q_CLASSINFO("DefaultProperty", "sprites")
+ public:
+     explicit QQuickSpriteSequence(QQuickItem *parent = 0);
++    QQmlListProperty<QQuickSprite> sprites();
+     bool running() const
+     {
+         return m_running;
+     }
+     bool interpolate() const
+     {
+         return m_interpolate;
+     }
+     QString goalSprite() const
+     {
+         return m_goalState;
+     }
+     QString currentSprite() const
+     {
+         return m_curState;
+     }
+ signals:
+     void runningChanged(bool arg);
+     void interpolateChanged(bool arg);
+     void goalSpriteChanged(QString arg);
+     void currentSpriteChanged(QString arg);
+ public slots:
+     void jumpTo(const QString &sprite);
+     void setGoalSprite(const QString &sprite);
+     void setRunning(bool arg)
+     {
+         if (m_running != arg) {
+             m_running = arg;
+             emit runningChanged(arg);
+         }
+     }
+     void setInterpolate(bool arg)
+     {
+         if (m_interpolate != arg) {
+             m_interpolate = arg;
+             emit interpolateChanged(arg);
+         }
+     }
+ private slots:
+     void createEngine();
+ protected:
+     void reset();
+     QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ private:
+     void prepareNextFrame();
+     QSGGeometryNode* buildNode();
+     QSGGeometryNode *m_node;
+     QQuickSpriteSequenceMaterial *m_material;
+     QList<QQuickSprite*> m_sprites;
+     QQuickSpriteEngine* m_spriteEngine;
+     QTime m_timestamp;
+     int m_curFrame;
+     bool m_pleaseReset;
+     bool m_running;
+     bool m_interpolate;
+     QString m_goalState;
+     QString m_curState;
+     int m_curStateIdx;
+     QSizeF m_sheetSize;
+ };
+ QT_END_NAMESPACE
+ QT_END_HEADER
+ #endif // QQUICKSPRITESEQUENCE_P_H
@@@ -299,12 -309,24 +310,24 @@@ void QQuickTextPrivate::updateLayout(
      if (!richText) {
          if (textHasChanged) {
              if (styledText && !text.isEmpty()) {
-                 QQuickStyledText::parse(text, layout, imgTags, q->baseUrl(), qmlContext(q), !maximumLineCountValid);
+                 layout.setFont(font);
+                 // needs temporary bool because formatModifiesFontSize is in a bit-field
+                 bool fontSizeModified = false;
 -                QDeclarativeStyledText::parse(text, layout, imgTags, q->baseUrl(), qmlContext(q), !maximumLineCountValid, &fontSizeModified);
++                QQuickStyledText::parse(text, layout, imgTags, q->baseUrl(), qmlContext(q), !maximumLineCountValid, &fontSizeModified);
+                 formatModifiesFontSize = fontSizeModified;
              } else {
                  layout.clearAdditionalFormats();
-                 multilengthEos = text.indexOf(QLatin1Char('\x9c'));
-                 QString tmp = multilengthEos != -1 ? text.mid(0, multilengthEos) : text;
-                 tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
+                 QString tmp = text;
+                 multilengthEos = tmp.indexOf(QLatin1Char('\x9c'));
+                 if (multilengthEos != -1) {
+                     tmp = tmp.mid(0, multilengthEos);
+                     tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
+                 } else if (tmp.contains(QLatin1Char('\n'))) {
+                     // Replace always does a detach.  Checking for the new line character first
+                     // means iterating over those items again if found but prevents a realloc
+                     // otherwise.
+                     tmp.replace(QLatin1Char('\n'), QChar::LineSeparator);
+                 }
                  layout.setText(tmp);
              }
              textHasChanged = false;
@@@ -340,9 -362,9 +363,9 @@@ void QQuickText::imageDownloadFinished(
      // if one of the sizes was not specified at parsing time
      // we use the implicit size from pixmapcache and re-layout.
  
-     if (d->nbActiveDownloads == 0) {
+     if (d->extra.isAllocated() && d->extra->nbActiveDownloads == 0) {
          bool needToUpdateLayout = false;
 -        foreach (QDeclarativeStyledTextImgTag *img, d->visibleImgTags) {
 +        foreach (QQuickStyledTextImgTag *img, d->visibleImgTags) {
              if (!img->size.isValid()) {
                  img->size = img->pix->implicitSize();
                  needToUpdateLayout = true;
@@@ -954,10 -1034,12 +1035,12 @@@ void QQuickTextPrivate::setLineGeometry
  
              if (!image->pix) {
                  QUrl url = q->baseUrl().resolved(image->url);
 -                image->pix = new QDeclarativePixmap(qmlEngine(q), url, image->size);
 +                image->pix = new QQuickPixmap(qmlEngine(q), url, image->size);
                  if (image->pix->isLoading()) {
                      image->pix->connectFinished(q, SLOT(imageDownloadFinished()));
-                     nbActiveDownloads++;
+                     if (!extra.isAllocated() || !extra->nbActiveDownloads)
+                         extra.value().nbActiveDownloads = 0;
+                     extra->nbActiveDownloads++;
                  } else if (image->pix->isReady()) {
                      if (!image->size.isValid()) {
                          image->size = image->pix->implicitSize();
  #include "qquicktext_p.h"
  #include "qquickimplicitsizeitem_p_p.h"
  
 -#include <QtDeclarative/qdeclarative.h>
 +#include <QtQml/qqml.h>
  #include <QtGui/qabstracttextdocumentlayout.h>
  #include <QtGui/qtextlayout.h>
 -#include <private/qdeclarativestyledtext_p.h>
 +#include <private/qquickstyledtext_p.h>
+ #include <private/qlazilyallocated_p.h>
  
  QT_BEGIN_NAMESPACE
  
@@@ -160,12 -168,16 +168,16 @@@ public
      bool isLinkActivatedConnected();
      QString anchorAt(const QPointF &pos);
  
-     static inline QQuickTextPrivate *get(QQuickText *t) {
-         return t->d_func();
-     }
+     inline qreal lineHeight() const { return extra.isAllocated() ? extra->lineHeight : 1.0; }
+     inline int maximumLineCount() const { return extra.isAllocated() ? extra->maximumLineCount : INT_MAX; }
+     inline QQuickText::LineHeightMode lineHeightMode() const { return extra.isAllocated() ? extra->lineHeightMode : QQuickText::ProportionalHeight; }
+     inline QQuickText::FontSizeMode fontSizeMode() const { return extra.isAllocated() ? extra->fontSizeMode : QQuickText::FixedSize; }
+     inline int minimumPixelSize() const { return extra.isAllocated() ? extra->minimumPixelSize : 12; }
+     inline int minimumPointSize() const { return extra.isAllocated() ? extra->minimumPointSize : 12; }
+     static inline QQuickTextPrivate *get(QQuickText *t) { return t->d_func(); }
  };
  
 -class QDeclarativePixmap;
 +class QQuickPixmap;
  class QQuickTextDocumentWithImageResources : public QTextDocument, public QTextObjectInterface
  {
      Q_OBJECT
Simple merge
@@@ -79,8 -79,8 +79,8 @@@ class Q_AUTOTEST_EXPORT QQuickTextEdit 
      Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
      Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
      Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
-     Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
+     Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
 -    Q_PROPERTY(QDeclarativeComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
 +    Q_PROPERTY(QQmlComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
      Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
      Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
      Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectionChanged)
@@@ -92,17 -94,42 +94,42 @@@ public
      void mirrorChange();
      qreal getImplicitWidth() const;
  
+     QColor color;
+     QColor selectionColor;
+     QColor selectedTextColor;
+     QSizeF contentSize;
+     qreal textMargin;
+     qreal yoff;
      QString text;
      QUrl baseUrl;
-     QFont font;
      QFont sourceFont;
-     QColor  color;
-     QColor  selectionColor;
-     QColor  selectedTextColor;
-     QString style;
-     QColor  styleColor;
+     QFont font;
 -    QDeclarativeComponent* cursorComponent;
++    QQmlComponent* cursorComponent;
+     QQuickItem* cursor;
+     QQuickTextDocumentWithImageResources *document;
+     QQuickTextControl *control;
+     int lastSelectionStart;
+     int lastSelectionEnd;
+     int lineCount;
+     enum UpdateType {
+         UpdateNone,
+         UpdateOnlyPreprocess,
+         UpdatePaintNode
+     };
      QQuickTextEdit::HAlignment hAlign;
      QQuickTextEdit::VAlignment vAlign;
+     QQuickTextEdit::TextFormat format;
+     QQuickTextEdit::WrapMode wrapMode;
+     QQuickTextEdit::SelectionMode mouseSelectionMode;
+     Qt::InputMethodHints inputMethodHints;
+     UpdateType updateType;
  
      bool documentDirty : 1;
      bool dirty : 1;
Simple merge
@@@ -76,8 -76,8 +76,8 @@@ class Q_AUTOTEST_EXPORT QQuickTextInpu
      Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
      Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
      Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
-     Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
+     Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
 -    Q_PROPERTY(QDeclarativeComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
 +    Q_PROPERTY(QQmlComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
      Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
      Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
      Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
@@@ -174,11 -174,14 +174,14 @@@ public
      QPointF pressPos;
      QPointF tripleClickStartPoint;
  
 -    QDeclarativeGuard<QDeclarativeComponent> cursorComponent;
 +    QQmlGuard<QQmlComponent> cursorComponent;
  #ifndef QT_NO_VALIDATOR
 -    QDeclarativeGuard<QValidator> m_validator;
 +    QQmlGuard<QValidator> m_validator;
  #endif
  
+     qreal hscroll;
+     qreal vscroll;
      QTextLayout m_textLayout;
      QString m_text;
      QString m_inputMask;
@@@ -450,8 -450,43 +450,43 @@@ QQuickVisualDataModel::ReleaseFlags QQu
      return stat;
  }
  
 -            if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(cacheItem->object))
+ // Cancel a requested async item
+ void QQuickVisualDataModel::cancel(int index)
+ {
+     Q_D(QQuickVisualDataModel);
+     if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
+         qWarning() << "VisualDataModel::cancel: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
+         return;
+     }
+     Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
+     QQuickVisualDataModelItem *cacheItem = it->inCache() ? d->m_cache.at(it.cacheIndex) : 0;
+     if (cacheItem) {
+         if (cacheItem->incubationTask) {
+             delete cacheItem->incubationTask->incubatingContext;
+             cacheItem->incubationTask->incubatingContext = 0;
+             d->releaseIncubator(cacheItem->incubationTask);
+             cacheItem->incubationTask = 0;
+         }
+         if (cacheItem->object && !cacheItem->isObjectReferenced()) {
+             d->destroy(cacheItem->object);
++            if (QQuickPackage *package = qobject_cast<QQuickPackage *>(cacheItem->object))
+                 d->emitDestroyingPackage(package);
+             else if (QQuickItem *item = qobject_cast<QQuickItem *>(cacheItem->object))
+                 d->emitDestroyingItem(item);
+             cacheItem->object = 0;
+         }
+         if (!cacheItem->isReferenced()) {
+             d->m_compositor.clearFlags(Compositor::Cache, it.cacheIndex, 1, Compositor::CacheFlag);
+             d->m_cache.removeAt(it.cacheIndex);
+             delete cacheItem;
+             Q_ASSERT(d->m_cache.count() == d->m_compositor.count(Compositor::Cache));
+         }
+     }
+ }
  void QQuickVisualDataModelPrivate::group_append(
 -        QDeclarativeListProperty<QQuickVisualDataGroup> *property, QQuickVisualDataGroup *group)
 +        QQmlListProperty<QQuickVisualDataGroup> *property, QQuickVisualDataGroup *group)
  {
      QQuickVisualDataModelPrivate *d = static_cast<QQuickVisualDataModelPrivate *>(property->data);
      if (d->m_complete)
  #include <QtCore/private/qabstractanimation_p.h>
  
  #include <QtGui/QOpenGLContext>
- #include <QtGui/QPlatformIntegration>
  #include <QtGui/private/qguiapplication_p.h>
+ #include <QtGui/qplatformintegration_qpa.h>
  
 -#include <QtDeclarative/private/qdeclarativeglobal_p.h>
 +#include <QtQml/private/qqmlglobal_p.h>
  
  #include <QtQuick/QQuickCanvas>
  #include <QtQuick/private/qquickcanvas_p.h>
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the Declarative module of the Qt Toolkit.
++** This file is part of the QtQuick module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the QtDeclarative module of the Qt Toolkit.
++** This file is part of the QtQml module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
@@@ -3,7 -3,7 +3,7 @@@
  ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  ** Contact: http://www.qt-project.org/
  **
--** This file is part of the QtDeclarative module of the Qt Toolkit.
++** This file is part of the QtQml module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:LGPL$
  ** GNU Lesser General Public License Usage
Simple merge
index 24b0b4e,0000000..2b2b2a8
mode 100644,000000..100644
--- /dev/null
@@@ -1,94 -1,0 +1,94 @@@
- QT_MODULE(Declarative)
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQUICKANIMATIONCONTROLLER_H
 +#define QQUICKANIMATIONCONTROLLER_H
 +
 +#include <qqml.h>
 +#include "qquickanimation_p.h"
 +
 +QT_BEGIN_HEADER
 +
 +QT_BEGIN_NAMESPACE
 +
++QT_MODULE(Quick)
 +
 +class QQuickAnimationControllerPrivate;
 +class Q_AUTOTEST_EXPORT QQuickAnimationController : public QObject, public QQmlParserStatus
 +{
 +    Q_OBJECT
 +    Q_INTERFACES(QQmlParserStatus)
 +
 +    Q_DECLARE_PRIVATE(QQuickAnimationController)
 +    Q_CLASSINFO("DefaultProperty", "animation")
 +
 +    Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
 +    Q_PROPERTY(QQuickAbstractAnimation *animation READ animation WRITE setAnimation NOTIFY animationChanged)
 +
 +public:
 +    QQuickAnimationController(QObject *parent=0);
 +    ~QQuickAnimationController();
 +
 +    qreal progress() const;
 +    void setProgress(qreal progress);
 +
 +    QQuickAbstractAnimation *animation() const;
 +    void setAnimation(QQuickAbstractAnimation *animation);
 +
 +    void classBegin();
 +    void componentComplete() {}
 +Q_SIGNALS:
 +    void progressChanged();
 +    void animationChanged();
 +public Q_SLOTS:
 +    void reload();
 +private Q_SLOTS:
 +    void componentFinalized();
 +    void updateProgress();
 +};
 +
 +QT_END_NAMESPACE
 +
 +QML_DECLARE_TYPE(QQuickAnimationController)
 +
 +QT_END_HEADER
 +
 +#endif // QQUICKANIMATIONCONTROLLER_H
index 85e155f,0000000..aae5306
mode 100644,000000..100644
--- /dev/null
@@@ -1,1278 -1,0 +1,1280 @@@
-     m_unreferencedCost += data->cost();
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include "qquickpixmapcache_p.h"
 +#include <qqmlnetworkaccessmanagerfactory.h>
 +#include <qqmlimageprovider.h>
 +
 +#include <qqmlengine.h>
 +#include <private/qqmlglobal_p.h>
 +#include <private/qqmlengine_p.h>
 +
 +#include <QtQuick/private/qsgtexture_p.h>
 +#include <QtQuick/private/qsgcontext_p.h>
 +
 +#include <QCoreApplication>
 +#include <QImageReader>
 +#include <QHash>
 +#include <QNetworkReply>
 +#include <QPixmapCache>
 +#include <QFile>
 +#include <QThread>
 +#include <QMutex>
 +#include <QMutexLocker>
 +#include <QWaitCondition>
 +#include <QBuffer>
 +#include <QWaitCondition>
 +#include <QtCore/qdebug.h>
 +#include <private/qobject_p.h>
 +#include <QSslError>
 +
 +#define IMAGEREQUEST_MAX_REQUEST_COUNT       8
 +#define IMAGEREQUEST_MAX_REDIRECT_RECURSION 16
 +#define CACHE_EXPIRE_TIME 30
 +#define CACHE_REMOVAL_FRACTION 4
 +
 +QT_BEGIN_NAMESPACE
 +
 +// The cache limit describes the maximum "junk" in the cache.
 +static int cache_limit = 2048 * 1024; // 2048 KB cache limit for embedded in qpixmapcache.cpp
 +
 +QSGTexture *QQuickDefaultTextureFactory::createTexture(QQuickCanvas *) const
 +{
 +    QSGPlainTexture *t = new QSGPlainTexture();
 +    t->setImage(im);
 +    return t;
 +}
 +
 +class QQuickPixmapReader;
 +class QQuickPixmapData;
 +class QQuickPixmapReply : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    enum ReadError { NoError, Loading, Decoding };
 +
 +    QQuickPixmapReply(QQuickPixmapData *);
 +    ~QQuickPixmapReply();
 +
 +    QQuickPixmapData *data;
 +    QQmlEngine *engineForReader; // always access reader inside readerMutex
 +    QSize requestSize;
 +    QUrl url;
 +
 +    bool loading;
 +    int redirectCount;
 +
 +    class Event : public QEvent {
 +    public:
 +        Event(ReadError, const QString &, const QSize &, QQuickTextureFactory *factory, const QImage &image);
 +
 +        ReadError error;
 +        QString errorString;
 +        QSize implicitSize;
 +        QImage image;
 +        QQuickTextureFactory *textureFactory;
 +    };
 +    void postReply(ReadError, const QString &, const QSize &, const QImage &image);
 +    void postReply(ReadError, const QString &, const QSize &, QQuickTextureFactory *factory, const QImage &image);
 +
 +
 +Q_SIGNALS:
 +    void finished();
 +    void downloadProgress(qint64, qint64);
 +
 +protected:
 +    bool event(QEvent *event);
 +
 +private:
 +    Q_DISABLE_COPY(QQuickPixmapReply)
 +
 +public:
 +    static int finishedIndex;
 +    static int downloadProgressIndex;
 +};
 +
 +class QQuickPixmapReaderThreadObject : public QObject {
 +    Q_OBJECT
 +public:
 +    QQuickPixmapReaderThreadObject(QQuickPixmapReader *);
 +    void processJobs();
 +    virtual bool event(QEvent *e);
 +private slots:
 +    void networkRequestDone();
 +private:
 +    QQuickPixmapReader *reader;
 +};
 +
 +class QQuickPixmapData;
 +class QQuickPixmapReader : public QThread
 +{
 +    Q_OBJECT
 +public:
 +    QQuickPixmapReader(QQmlEngine *eng);
 +    ~QQuickPixmapReader();
 +
 +    QQuickPixmapReply *getImage(QQuickPixmapData *);
 +    void cancel(QQuickPixmapReply *rep);
 +
 +    static QQuickPixmapReader *instance(QQmlEngine *engine);
 +    static QQuickPixmapReader *existingInstance(QQmlEngine *engine);
 +
 +protected:
 +    void run();
 +
 +private:
 +    friend class QQuickPixmapReaderThreadObject;
 +    void processJobs();
 +    void processJob(QQuickPixmapReply *, const QUrl &, const QSize &);
 +    void networkRequestDone(QNetworkReply *);
 +
 +    QList<QQuickPixmapReply*> jobs;
 +    QList<QQuickPixmapReply*> cancelled;
 +    QQmlEngine *engine;
 +    QObject *eventLoopQuitHack;
 +
 +    QMutex mutex;
 +    QQuickPixmapReaderThreadObject *threadObject;
 +    QWaitCondition waitCondition;
 +
 +    QNetworkAccessManager *networkAccessManager();
 +    QNetworkAccessManager *accessManager;
 +
 +    QHash<QNetworkReply*,QQuickPixmapReply*> replies;
 +
 +    static int replyDownloadProgress;
 +    static int replyFinished;
 +    static int downloadProgress;
 +    static int threadNetworkRequestDone;
 +    static QHash<QQmlEngine *,QQuickPixmapReader*> readers;
 +public:
 +    static QMutex readerMutex;
 +};
 +
 +class QQuickPixmapData
 +{
 +public:
 +    QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &s, const QString &e)
 +    : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Error), 
 +      url(u), errorString(e), requestSize(s), textureFactory(0), reply(0), prevUnreferenced(0),
 +      prevUnreferencedPtr(0), nextUnreferenced(0)
 +    {
 +        declarativePixmaps.insert(pixmap);
 +    }
 +
 +    QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &r)
 +    : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Loading), 
 +      url(u), requestSize(r), textureFactory(0), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0),
 +      nextUnreferenced(0)
 +    {
 +        declarativePixmaps.insert(pixmap);
 +    }
 +
 +    QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QImage &p, const QSize &s, const QSize &r)
 +    : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QQuickPixmap::Ready),
 +      url(u), image(p), implicitSize(s), requestSize(r), textureFactory(new QQuickDefaultTextureFactory(p)), reply(0), prevUnreferenced(0),
 +      prevUnreferencedPtr(0), nextUnreferenced(0)
 +    {
 +        declarativePixmaps.insert(pixmap);
 +    }
 +
 +    QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, QQuickTextureFactory *factory, const QImage &p, const QSize &s, const QSize &r)
 +    : refCount(1), inCache(false), privatePixmap(false), pixmapStatus(QQuickPixmap::Ready),
 +      url(u), image(p), implicitSize(s), requestSize(r), textureFactory(factory), reply(0), prevUnreferenced(0),
 +      prevUnreferencedPtr(0), nextUnreferenced(0)
 +    {
 +        declarativePixmaps.insert(pixmap);
 +    }
 +
 +    QQuickPixmapData(QQuickPixmap *pixmap, const QImage &p)
 +    : refCount(1), inCache(false), privatePixmap(true), pixmapStatus(QQuickPixmap::Ready),
 +      image(p), implicitSize(p.size()), requestSize(p.size()), textureFactory(new QQuickDefaultTextureFactory(p)), reply(0), prevUnreferenced(0),
 +      prevUnreferencedPtr(0), nextUnreferenced(0)
 +    {
 +        declarativePixmaps.insert(pixmap);
 +    }
 +
 +    ~QQuickPixmapData()
 +    {
 +        while (!declarativePixmaps.isEmpty()) {
 +            QQuickPixmap *referencer = declarativePixmaps.first();
 +            declarativePixmaps.remove(referencer);
 +            referencer->d = 0;
 +        }
 +        delete textureFactory;
 +    }
 +
 +    int cost() const;
 +    void addref();
 +    void release();
 +    void addToCache();
 +    void removeFromCache();
 +
 +    uint refCount;
 +
 +    bool inCache:1;
 +    bool privatePixmap:1;
 +    
 +    QQuickPixmap::Status pixmapStatus;
 +    QUrl url;
 +    QString errorString;
 +    QImage image;
 +    QSize implicitSize;
 +    QSize requestSize;
 +
 +    QQuickTextureFactory *textureFactory;
 +
 +    QIntrusiveList<QQuickPixmap, &QQuickPixmap::dataListNode> declarativePixmaps;
 +    QQuickPixmapReply *reply;
 +
 +    QQuickPixmapData *prevUnreferenced;
 +    QQuickPixmapData**prevUnreferencedPtr;
 +    QQuickPixmapData *nextUnreferenced;
 +};
 +
 +int QQuickPixmapReply::finishedIndex = -1;
 +int QQuickPixmapReply::downloadProgressIndex = -1;
 +
 +// XXX
 +QHash<QQmlEngine *,QQuickPixmapReader*> QQuickPixmapReader::readers;
 +QMutex QQuickPixmapReader::readerMutex;
 +
 +int QQuickPixmapReader::replyDownloadProgress = -1;
 +int QQuickPixmapReader::replyFinished = -1;
 +int QQuickPixmapReader::downloadProgress = -1;
 +int QQuickPixmapReader::threadNetworkRequestDone = -1;
 +
 +
 +void QQuickPixmapReply::postReply(ReadError error, const QString &errorString,
 +                                        const QSize &implicitSize, const QImage &image)
 +{
 +    loading = false;
 +    QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, new QQuickDefaultTextureFactory(image), image));
 +}
 +
 +void QQuickPixmapReply::postReply(ReadError error, const QString &errorString,
 +                                        const QSize &implicitSize, QQuickTextureFactory *factory,
 +                                        const QImage &image)
 +{
 +    loading = false;
 +    QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, factory, image));
 +}
 +
 +QQuickPixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, QQuickTextureFactory *factory, const QImage &i)
 +    : QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), image(i), textureFactory(factory)
 +{
 +}
 +
 +QNetworkAccessManager *QQuickPixmapReader::networkAccessManager()
 +{
 +    if (!accessManager) {
 +        Q_ASSERT(threadObject);
 +        accessManager = QQmlEnginePrivate::get(engine)->createNetworkAccessManager(threadObject);
 +    }
 +    return accessManager;
 +}
 +
 +static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, 
 +                      const QSize &requestSize)
 +{
 +    QImageReader imgio(dev);
 +
 +    bool force_scale = false;
 +    if (url.path().endsWith(QLatin1String(".svg"),Qt::CaseInsensitive)) {
 +        imgio.setFormat("svg"); // QSvgPlugin::capabilities bug QTBUG-9053
 +        force_scale = true;
 +    }
 +
 +    if (requestSize.width() > 0 || requestSize.height() > 0) {
 +        QSize s = imgio.size();
 +        qreal ratio = 0.0;
 +        if (requestSize.width() && (force_scale || requestSize.width() < s.width())) {
 +            ratio = qreal(requestSize.width())/s.width();
 +        }
 +        if (requestSize.height() && (force_scale || requestSize.height() < s.height())) {
 +            qreal hr = qreal(requestSize.height())/s.height();
 +            if (ratio == 0.0 || hr < ratio)
 +                ratio = hr;
 +        }
 +        if (ratio > 0.0) {
 +            s.setHeight(qRound(s.height() * ratio));
 +            s.setWidth(qRound(s.width() * ratio));
 +            imgio.setScaledSize(s);
 +        }
 +    }
 +
 +    if (impsize)
 +        *impsize = imgio.size();
 +
 +    if (imgio.read(image)) {
 +        if (impsize && impsize->width() < 0)
 +            *impsize = image->size();
 +        return true;
 +    } else {
 +        if (errorString)
 +            *errorString = QQuickPixmap::tr("Error decoding: %1: %2").arg(url.toString())
 +                                .arg(imgio.errorString());
 +        return false;
 +    }
 +}
 +
 +QQuickPixmapReader::QQuickPixmapReader(QQmlEngine *eng)
 +: QThread(eng), engine(eng), threadObject(0), accessManager(0)
 +{
 +    eventLoopQuitHack = new QObject;
 +    eventLoopQuitHack->moveToThread(this);
 +    connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection);
 +    start(QThread::LowestPriority);
 +}
 +
 +QQuickPixmapReader::~QQuickPixmapReader()
 +{
 +    readerMutex.lock();
 +    readers.remove(engine);
 +    readerMutex.unlock();
 +
 +    mutex.lock();
 +    // manually cancel all outstanding jobs.
 +    foreach (QQuickPixmapReply *reply, jobs) {
 +        delete reply;
 +    }
 +    jobs.clear();
 +    QList<QQuickPixmapReply*> activeJobs = replies.values();
 +    foreach (QQuickPixmapReply *reply, activeJobs) {
 +        if (reply->loading) {
 +            cancelled.append(reply);
 +            reply->data = 0;
 +        }
 +    }
 +    if (threadObject) threadObject->processJobs();
 +    mutex.unlock();
 +
 +    eventLoopQuitHack->deleteLater();
 +    wait();
 +}
 +
 +void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply)
 +{
 +    QQuickPixmapReply *job = replies.take(reply);
 +
 +    if (job) {
 +        job->redirectCount++;
 +        if (job->redirectCount < IMAGEREQUEST_MAX_REDIRECT_RECURSION) {
 +            QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
 +            if (redirect.isValid()) {
 +                QUrl url = reply->url().resolved(redirect.toUrl());
 +                QNetworkRequest req(url);
 +                req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
 +
 +                reply->deleteLater();
 +                reply = networkAccessManager()->get(req);
 +
 +                QMetaObject::connect(reply, replyDownloadProgress, job, downloadProgress);
 +                QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
 +
 +                replies.insert(reply, job);
 +                return;
 +            }
 +        }
 +
 +        QImage image;
 +        QQuickPixmapReply::ReadError error = QQuickPixmapReply::NoError;
 +        QString errorString;
 +        QSize readSize;
 +        if (reply->error()) {
 +            error = QQuickPixmapReply::Loading;
 +            errorString = reply->errorString();
 +        } else {
 +            QByteArray all = reply->readAll();
 +            QBuffer buff(&all);
 +            buff.open(QIODevice::ReadOnly);
 +            if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize))
 +                error = QQuickPixmapReply::Decoding;
 +       }
 +        // send completion event to the QQuickPixmapReply
 +        mutex.lock();
 +        if (!cancelled.contains(job)) {
 +            QQuickTextureFactory *factory = QSGContext::createTextureFactoryFromImage(image);
 +            if (factory)
 +                job->postReply(error, errorString, readSize, factory, image);
 +            else
 +                job->postReply(error, errorString, readSize, image);
 +        }
 +        mutex.unlock();
 +    }
 +    reply->deleteLater();
 +
 +    // kick off event loop again incase we have dropped below max request count
 +    threadObject->processJobs();
 +}
 +
 +QQuickPixmapReaderThreadObject::QQuickPixmapReaderThreadObject(QQuickPixmapReader *i)
 +: reader(i)
 +{
 +}
 +
 +void QQuickPixmapReaderThreadObject::processJobs() 
 +{ 
 +    QCoreApplication::postEvent(this, new QEvent(QEvent::User)); 
 +}
 +
 +bool QQuickPixmapReaderThreadObject::event(QEvent *e) 
 +{
 +    if (e->type() == QEvent::User) { 
 +        reader->processJobs(); 
 +        return true; 
 +    } else { 
 +        return QObject::event(e);
 +    }
 +}
 +
 +void QQuickPixmapReaderThreadObject::networkRequestDone()
 +{
 +    QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
 +    reader->networkRequestDone(reply);
 +}
 +
 +void QQuickPixmapReader::processJobs()
 +{
 +    QMutexLocker locker(&mutex);
 +
 +    while (true) {
 +        if (cancelled.isEmpty() && (jobs.isEmpty() || replies.count() >= IMAGEREQUEST_MAX_REQUEST_COUNT)) 
 +            return; // Nothing else to do
 +
 +        // Clean cancelled jobs
 +        if (cancelled.count()) {
 +            for (int i = 0; i < cancelled.count(); ++i) {
 +                QQuickPixmapReply *job = cancelled.at(i);
 +                QNetworkReply *reply = replies.key(job, 0);
 +                if (reply && reply->isRunning()) {
 +                    // cancel any jobs already started
 +                    replies.remove(reply);
 +                    reply->close();
 +                }
 +                // deleteLater, since not owned by this thread
 +                job->deleteLater();
 +            }
 +            cancelled.clear();
 +        }
 +
 +        if (!jobs.isEmpty() && replies.count() < IMAGEREQUEST_MAX_REQUEST_COUNT) {
 +            QQuickPixmapReply *runningJob = jobs.takeLast();
 +            runningJob->loading = true;
 +
 +            QUrl url = runningJob->url;
 +            QSize requestSize = runningJob->requestSize;
 +            locker.unlock();
 +            processJob(runningJob, url, requestSize);
 +            locker.relock();
 +        }
 +    }
 +}
 +
 +void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url, 
 +                                          const QSize &requestSize)
 +{
 +    // fetch
 +    if (url.scheme() == QLatin1String("image")) {
 +        // Use QmlImageProvider
 +        QSize readSize;
 +        QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
 +        QQmlImageProvider::ImageType imageType = ep->getImageProviderType(url);
 +        if (imageType == QQmlImageProvider::Invalid) {
 +            QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::Loading;
 +            QString errorStr = QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString());
 +            QImage image;
 +            mutex.lock();
 +            if (!cancelled.contains(runningJob))
 +                runningJob->postReply(errorCode, errorStr, readSize, image);
 +            mutex.unlock();
 +        } else if (imageType == QQmlImageProvider::Image) {
 +            QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
 +            QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
 +            QString errorStr;
 +            if (image.isNull()) {
 +                errorCode = QQuickPixmapReply::Loading;
 +                errorStr = QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString());
 +            }
 +            mutex.lock();
 +            if (!cancelled.contains(runningJob)) {
 +                QQuickTextureFactory *factory = QSGContext::createTextureFactoryFromImage(image);
 +                if (factory)
 +                    runningJob->postReply(errorCode, errorStr, readSize, factory, image);
 +                else
 +                    runningJob->postReply(errorCode, errorStr, readSize, image);
 +            }
 +
 +            mutex.unlock();
 +        } else {
 +            QQuickTextureFactory *t = ep->getTextureFromProvider(url, &readSize, requestSize);
 +            QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
 +            QString errorStr;
 +            if (!t) {
 +                errorCode = QQuickPixmapReply::Loading;
 +                errorStr = QQuickPixmap::tr("Failed to get texture from provider: %1").arg(url.toString());
 +            }
 +            mutex.lock();
 +            if (!cancelled.contains(runningJob))
 +                runningJob->postReply(errorCode, errorStr, readSize, t, QImage());
 +            mutex.unlock();
 +
 +        }
 +
 +    } else {
 +        QString lf = QQmlEnginePrivate::urlToLocalFileOrQrc(url);
 +        if (!lf.isEmpty()) {
 +            // Image is local - load/decode immediately
 +            QImage image;
 +            QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError;
 +            QString errorStr;
 +            QFile f(lf);
 +            QSize readSize;
 +            if (f.open(QIODevice::ReadOnly)) {
 +                if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize))
 +                    errorCode = QQuickPixmapReply::Loading;
 +            } else {
 +                errorStr = QQuickPixmap::tr("Cannot open: %1").arg(url.toString());
 +                errorCode = QQuickPixmapReply::Loading;
 +            }
 +            mutex.lock();
 +            if (!cancelled.contains(runningJob)) {
 +                QQuickTextureFactory *factory = QSGContext::createTextureFactoryFromImage(image);
 +                if (factory)
 +                    runningJob->postReply(errorCode, errorStr, readSize, factory, image);
 +                else
 +                    runningJob->postReply(errorCode, errorStr, readSize, image);
 +            }
 +            mutex.unlock();
 +        } else {
 +            // Network resource
 +            QNetworkRequest req(url);
 +            req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
 +            QNetworkReply *reply = networkAccessManager()->get(req);
 +
 +            QMetaObject::connect(reply, replyDownloadProgress, runningJob, downloadProgress);
 +            QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone);
 +
 +            replies.insert(reply, runningJob);
 +        }
 +    }
 +}
 +
 +QQuickPixmapReader *QQuickPixmapReader::instance(QQmlEngine *engine)
 +{
 +    // XXX NOTE: must be called within readerMutex locking.
 +    QQuickPixmapReader *reader = readers.value(engine);
 +    if (!reader) {
 +        reader = new QQuickPixmapReader(engine);
 +        readers.insert(engine, reader);
 +    }
 +
 +    return reader;
 +}
 +
 +QQuickPixmapReader *QQuickPixmapReader::existingInstance(QQmlEngine *engine)
 +{
 +    // XXX NOTE: must be called within readerMutex locking.
 +    return readers.value(engine, 0);
 +}
 +
 +QQuickPixmapReply *QQuickPixmapReader::getImage(QQuickPixmapData *data)
 +{
 +    mutex.lock();
 +    QQuickPixmapReply *reply = new QQuickPixmapReply(data);
 +    reply->engineForReader = engine;
 +    jobs.append(reply);
 +    // XXX 
 +    if (threadObject) threadObject->processJobs();
 +    mutex.unlock();
 +    return reply;
 +}
 +
 +void QQuickPixmapReader::cancel(QQuickPixmapReply *reply)
 +{
 +    mutex.lock();
 +    if (reply->loading) {
 +        cancelled.append(reply);
 +        reply->data = 0;
 +        // XXX 
 +        if (threadObject) threadObject->processJobs();
 +    } else {
 +        jobs.removeAll(reply);
 +        delete reply;
 +    }
 +    mutex.unlock();
 +}
 +
 +void QQuickPixmapReader::run()
 +{
 +    if (replyDownloadProgress == -1) {
 +        const QMetaObject *nr = &QNetworkReply::staticMetaObject;
 +        const QMetaObject *pr = &QQuickPixmapReply::staticMetaObject;
 +        const QMetaObject *ir = &QQuickPixmapReaderThreadObject::staticMetaObject;
 +        replyDownloadProgress = nr->indexOfSignal("downloadProgress(qint64,qint64)");
 +        replyFinished = nr->indexOfSignal("finished()");
 +        downloadProgress = pr->indexOfSignal("downloadProgress(qint64,qint64)");
 +        threadNetworkRequestDone = ir->indexOfSlot("networkRequestDone()");
 +    }
 +
 +    mutex.lock();
 +    threadObject = new QQuickPixmapReaderThreadObject(this);
 +    mutex.unlock();
 +
 +    processJobs();
 +    exec();
 +
 +    delete threadObject;
 +    threadObject = 0;
 +}
 +
 +class QQuickPixmapKey
 +{
 +public:
 +    const QUrl *url;
 +    const QSize *size;
 +};
 +
 +inline bool operator==(const QQuickPixmapKey &lhs, const QQuickPixmapKey &rhs)
 +{
 +    return *lhs.size == *rhs.size && *lhs.url == *rhs.url;
 +}
 +
 +inline uint qHash(const QQuickPixmapKey &key)
 +{
 +    return qHash(*key.url) ^ key.size->width() ^ key.size->height();
 +}
 +
 +class QSGContext;
 +
 +class QQuickPixmapStore : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    QQuickPixmapStore();
 +    ~QQuickPixmapStore();
 +
 +    void unreferencePixmap(QQuickPixmapData *);
 +    void referencePixmap(QQuickPixmapData *);
 +
 +    void purgeCache();
 +
 +protected:
 +    virtual void timerEvent(QTimerEvent *);
 +
 +public:
 +    QHash<QQuickPixmapKey, QQuickPixmapData *> m_cache;
 +
 +private:
 +    void shrinkCache(int remove);
 +
 +    QQuickPixmapData *m_unreferencedPixmaps;
 +    QQuickPixmapData *m_lastUnreferencedPixmap;
 +
 +    int m_unreferencedCost;
 +    int m_timerId;
 +    bool m_destroying;
 +};
 +Q_GLOBAL_STATIC(QQuickPixmapStore, pixmapStore);
 +
 +
 +QQuickPixmapStore::QQuickPixmapStore()
 +    : m_unreferencedPixmaps(0), m_lastUnreferencedPixmap(0), m_unreferencedCost(0), m_timerId(-1), m_destroying(false)
 +{
 +}
 +
 +QQuickPixmapStore::~QQuickPixmapStore()
 +{
 +    m_destroying = true;
 +
 +    int leakedPixmaps = 0;
 +    QList<QQuickPixmapData*> cachedData = m_cache.values();
 +
 +    // Prevent unreferencePixmap() from assuming it needs to kick
 +    // off the cache expiry timer, as we're shrinking the cache
 +    // manually below after releasing all the pixmaps.
 +    m_timerId = -2;
 +
 +    // unreference all (leaked) pixmaps
 +    foreach (QQuickPixmapData* pixmap, cachedData) {
 +        int currRefCount = pixmap->refCount;
 +        if (currRefCount) {
 +            leakedPixmaps++;
 +            while (currRefCount > 0) {
 +                pixmap->release();
 +                currRefCount--;
 +            }
 +        }
 +    }
 +
 +    // free all unreferenced pixmaps
 +    while (m_lastUnreferencedPixmap) {
 +        shrinkCache(20);
 +    }
 +
 +    if (leakedPixmaps)
 +        qDebug("Number of leaked pixmaps: %i", leakedPixmaps);
 +}
 +
 +void QQuickPixmapStore::unreferencePixmap(QQuickPixmapData *data)
 +{
 +    Q_ASSERT(data->prevUnreferenced == 0);
 +    Q_ASSERT(data->prevUnreferencedPtr == 0);
 +    Q_ASSERT(data->nextUnreferenced == 0);
 +
 +    data->nextUnreferenced = m_unreferencedPixmaps;
 +    data->prevUnreferencedPtr = &m_unreferencedPixmaps;
++    if (!m_destroying) // the texture factories may have been cleaned up already.
++        m_unreferencedCost += data->cost();
 +
 +    m_unreferencedPixmaps = data;
 +    if (m_unreferencedPixmaps->nextUnreferenced) {
 +        m_unreferencedPixmaps->nextUnreferenced->prevUnreferenced = m_unreferencedPixmaps;
 +        m_unreferencedPixmaps->nextUnreferenced->prevUnreferencedPtr = &m_unreferencedPixmaps->nextUnreferenced;
 +    }
 +
 +    if (!m_lastUnreferencedPixmap)
 +        m_lastUnreferencedPixmap = data;
 +
-         remove -= data->cost();
-         m_unreferencedCost -= data->cost();
 +    shrinkCache(-1); // Shrink the cache incase it has become larger than cache_limit
 +
 +    if (m_timerId == -1 && m_unreferencedPixmaps && !m_destroying)
 +        m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
 +}
 +
 +void QQuickPixmapStore::referencePixmap(QQuickPixmapData *data)
 +{
 +    Q_ASSERT(data->prevUnreferencedPtr);
 +
 +    *data->prevUnreferencedPtr = data->nextUnreferenced;
 +    if (data->nextUnreferenced) { 
 +        data->nextUnreferenced->prevUnreferencedPtr = data->prevUnreferencedPtr;
 +        data->nextUnreferenced->prevUnreferenced = data->prevUnreferenced;
 +    }
 +    if (m_lastUnreferencedPixmap == data)
 +        m_lastUnreferencedPixmap = data->prevUnreferenced;
 +
 +    data->nextUnreferenced = 0;
 +    data->prevUnreferencedPtr = 0;
 +    data->prevUnreferenced = 0;
 +
 +    m_unreferencedCost -= data->cost();
 +}
 +
 +void QQuickPixmapStore::shrinkCache(int remove)
 +{
 +    while ((remove > 0 || m_unreferencedCost > cache_limit) && m_lastUnreferencedPixmap) {
 +        QQuickPixmapData *data = m_lastUnreferencedPixmap;
 +        Q_ASSERT(data->nextUnreferenced == 0);
 +
 +        *data->prevUnreferencedPtr = 0;
 +        m_lastUnreferencedPixmap = data->prevUnreferenced;
 +        data->prevUnreferencedPtr = 0;
 +        data->prevUnreferenced = 0;
 +
++        if (!m_destroying) {
++            remove -= data->cost();
++            m_unreferencedCost -= data->cost();
++        }
 +        data->removeFromCache();
 +        delete data;
 +    }
 +}
 +
 +void QQuickPixmapStore::timerEvent(QTimerEvent *)
 +{
 +    int removalCost = m_unreferencedCost / CACHE_REMOVAL_FRACTION;
 +
 +    shrinkCache(removalCost);
 +
 +    if (m_unreferencedPixmaps == 0) {
 +        killTimer(m_timerId);
 +        m_timerId = -1;
 +    }
 +}
 +
 +void QQuickPixmapStore::purgeCache()
 +{
 +    shrinkCache(m_unreferencedCost);
 +}
 +
 +void QQuickPixmap::purgeCache()
 +{
 +    pixmapStore()->purgeCache();
 +}
 +
 +QQuickPixmapReply::QQuickPixmapReply(QQuickPixmapData *d)
 +: data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), redirectCount(0)
 +{
 +    if (finishedIndex == -1) {
 +        finishedIndex = QQuickPixmapReply::staticMetaObject.indexOfSignal("finished()");
 +        downloadProgressIndex = QQuickPixmapReply::staticMetaObject.indexOfSignal("downloadProgress(qint64,qint64)");
 +    }
 +}
 +
 +QQuickPixmapReply::~QQuickPixmapReply()
 +{
 +}
 +
 +bool QQuickPixmapReply::event(QEvent *event)
 +{
 +    if (event->type() == QEvent::User) {
 +
 +        if (data) {
 +            Event *de = static_cast<Event *>(event);
 +            data->pixmapStatus = (de->error == NoError) ? QQuickPixmap::Ready : QQuickPixmap::Error;
 +
 +            if (data->pixmapStatus == QQuickPixmap::Ready) {
 +                if (de->textureFactory) {
 +                    data->textureFactory = de->textureFactory;
 +                }
 +                data->image = de->image;
 +                data->implicitSize = de->implicitSize;
 +            } else {
 +                data->errorString = de->errorString;
 +                data->removeFromCache(); // We don't continue to cache error'd pixmaps
 +            }
 +
 +            data->reply = 0;
 +            emit finished();
 +        }
 +
 +        delete this;
 +        return true;
 +    } else {
 +        return QObject::event(event);
 +    }
 +}
 +
 +int QQuickPixmapData::cost() const
 +{
 +    if (textureFactory)
 +        return textureFactory->textureByteCount();
 +    return image.byteCount();
 +}
 +
 +void QQuickPixmapData::addref()
 +{
 +    ++refCount;
 +    if (prevUnreferencedPtr) 
 +        pixmapStore()->referencePixmap(this);
 +}
 +
 +void QQuickPixmapData::release()
 +{
 +    Q_ASSERT(refCount > 0);
 +    --refCount;
 +    if (refCount == 0) {
 +        if (reply) {
 +            QQuickPixmapReply *cancelReply = reply;
 +            reply->data = 0;
 +            reply = 0;
 +            QQuickPixmapReader::readerMutex.lock();
 +            QQuickPixmapReader *reader = QQuickPixmapReader::existingInstance(cancelReply->engineForReader);
 +            if (reader)
 +                reader->cancel(cancelReply);
 +            QQuickPixmapReader::readerMutex.unlock();
 +        }
 +
 +        if (pixmapStatus == QQuickPixmap::Ready) {
 +            pixmapStore()->unreferencePixmap(this);
 +        } else {
 +            removeFromCache();
 +            delete this;
 +        }
 +    }
 +}
 +
 +void QQuickPixmapData::addToCache()
 +{
 +    if (!inCache) {
 +        QQuickPixmapKey key = { &url, &requestSize };
 +        pixmapStore()->m_cache.insert(key, this);
 +        inCache = true;
 +    }
 +}
 +
 +void QQuickPixmapData::removeFromCache()
 +{
 +    if (inCache) {
 +        QQuickPixmapKey key = { &url, &requestSize };
 +        pixmapStore()->m_cache.remove(key);
 +        inCache = false;
 +    }
 +}
 +
 +static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, QQmlEngine *engine, const QUrl &url, const QSize &requestSize, bool *ok)
 +{
 +    if (url.scheme() == QLatin1String("image")) {
 +        QSize readSize;
 +        QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
 +        QQmlImageProvider::ImageType imageType = ep->getImageProviderType(url);
 +
 +        switch (imageType) {
 +            case QQmlImageProvider::Invalid:
 +                return new QQuickPixmapData(declarativePixmap, url, requestSize,
 +                    QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString()));
 +            case QQmlImageProvider::Texture:
 +            {
 +                QQuickTextureFactory *texture = ep->getTextureFromProvider(url, &readSize, requestSize);
 +                if (texture) {
 +                    *ok = true;
 +                    return new QQuickPixmapData(declarativePixmap, url, texture, QImage(), readSize, requestSize);
 +                }
 +            }
 +
 +            case QQmlImageProvider::Image:
 +            {
 +                QImage image = ep->getImageFromProvider(url, &readSize, requestSize);
 +                if (!image.isNull()) {
 +                    *ok = true;
 +                    return new QQuickPixmapData(declarativePixmap, url, image, readSize, requestSize);
 +                }
 +            }
 +            case QQmlImageProvider::Pixmap:
 +            {
 +                QPixmap pixmap = ep->getPixmapFromProvider(url, &readSize, requestSize);
 +                if (!pixmap.isNull()) {
 +                    *ok = true;
 +                    return new QQuickPixmapData(declarativePixmap, url, pixmap.toImage(), readSize, requestSize);
 +                }
 +            }
 +        }
 +
 +        // provider has bad image type, or provider returned null image
 +        return new QQuickPixmapData(declarativePixmap, url, requestSize,
 +            QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString()));
 +    }
 +
 +    QString localFile = QQmlEnginePrivate::urlToLocalFileOrQrc(url);
 +    if (localFile.isEmpty()) 
 +        return 0;
 +
 +    QFile f(localFile);
 +    QSize readSize;
 +    QString errorString;
 +
 +    if (f.open(QIODevice::ReadOnly)) {
 +        QImage image;
 +
 +        if (readImage(url, &f, &image, &errorString, &readSize, requestSize)) {
 +            *ok = true;
 +            return new QQuickPixmapData(declarativePixmap, url, image, readSize, requestSize);
 +        }
 +        errorString = QQuickPixmap::tr("Invalid image data: %1").arg(url.toString());
 +
 +    } else {
 +        errorString = QQuickPixmap::tr("Cannot open: %1").arg(url.toString());
 +    }
 +    return new QQuickPixmapData(declarativePixmap, url, requestSize, errorString);
 +}
 +
 +
 +struct QQuickPixmapNull {
 +    QUrl url;
 +    QImage image;
 +    QSize size;
 +};
 +Q_GLOBAL_STATIC(QQuickPixmapNull, nullPixmap);
 +
 +QQuickPixmap::QQuickPixmap()
 +: d(0)
 +{
 +}
 +
 +QQuickPixmap::QQuickPixmap(QQmlEngine *engine, const QUrl &url)
 +: d(0)
 +{
 +    load(engine, url);
 +}
 +
 +QQuickPixmap::QQuickPixmap(QQmlEngine *engine, const QUrl &url, const QSize &size)
 +: d(0)
 +{
 +    load(engine, url, size);
 +}
 +
 +QQuickPixmap::~QQuickPixmap()
 +{
 +    if (d) {
 +        d->declarativePixmaps.remove(this);
 +        d->release();
 +        d = 0;
 +    }
 +}
 +
 +bool QQuickPixmap::isNull() const
 +{
 +    return d == 0;
 +}
 +
 +bool QQuickPixmap::isReady() const
 +{
 +    return status() == Ready;
 +}
 +
 +bool QQuickPixmap::isError() const
 +{
 +    return status() == Error;
 +}
 +
 +bool QQuickPixmap::isLoading() const
 +{
 +    return status() == Loading;
 +}
 +
 +QString QQuickPixmap::error() const
 +{
 +    if (d)
 +        return d->errorString;
 +    else
 +        return QString();
 +}
 +
 +QQuickPixmap::Status QQuickPixmap::status() const
 +{
 +    if (d)
 +        return d->pixmapStatus;
 +    else
 +        return Null;
 +}
 +
 +const QUrl &QQuickPixmap::url() const
 +{
 +    if (d)
 +        return d->url;
 +    else
 +        return nullPixmap()->url;
 +}
 +
 +const QSize &QQuickPixmap::implicitSize() const
 +{
 +    if (d) 
 +        return d->implicitSize;
 +    else
 +        return nullPixmap()->size;
 +}
 +
 +const QSize &QQuickPixmap::requestSize() const
 +{
 +    if (d)
 +        return d->requestSize;
 +    else
 +        return nullPixmap()->size;
 +}
 +
 +QQuickTextureFactory *QQuickPixmap::textureFactory() const
 +{
 +    if (d)
 +        return d->textureFactory;
 +
 +    return 0;
 +}
 +
 +const QImage &QQuickPixmap::image() const
 +{
 +    if (d) 
 +        return d->image;
 +    else
 +        return nullPixmap()->image;
 +}
 +
 +void QQuickPixmap::setImage(const QImage &p)
 +{
 +    clear();
 +
 +    if (!p.isNull())
 +        d = new QQuickPixmapData(this, p);
 +}
 +
 +int QQuickPixmap::width() const
 +{
 +    if (d) 
 +        return d->textureFactory ? d->textureFactory->textureSize().width() : d->image.width();
 +    else
 +        return 0;
 +}
 +
 +int QQuickPixmap::height() const
 +{
 +    if (d) 
 +        return d->textureFactory ? d->textureFactory->textureSize().height() : d->image.height();
 +    else
 +        return 0;
 +}
 +
 +QRect QQuickPixmap::rect() const
 +{
 +    if (d)
 +        return d->textureFactory ? QRect(QPoint(), d->textureFactory->textureSize()) : d->image.rect();
 +    else
 +        return QRect();
 +}
 +
 +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url)
 +{
 +    load(engine, url, QSize(), QQuickPixmap::Cache);
 +}
 +
 +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, QQuickPixmap::Options options)
 +{
 +    load(engine, url, QSize(), options);
 +}
 +
 +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &size)
 +{
 +    load(engine, url, size, QQuickPixmap::Cache);
 +}
 +
 +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options)
 +{
 +    if (d) {
 +        d->declarativePixmaps.remove(this);
 +        d->release();
 +        d = 0;
 +    }
 +
 +    QQuickPixmapKey key = { &url, &requestSize };
 +    QQuickPixmapStore *store = pixmapStore();
 +
 +    QHash<QQuickPixmapKey, QQuickPixmapData *>::Iterator iter = store->m_cache.find(key);
 +
 +    if (iter == store->m_cache.end()) {
 +        if (options & QQuickPixmap::Asynchronous) {
 +            // pixmaps can only be loaded synchronously
 +            if (url.scheme() == QLatin1String("image") 
 +                    && QQmlEnginePrivate::get(engine)->getImageProviderType(url) == QQmlImageProvider::Pixmap) {
 +                options &= ~QQuickPixmap::Asynchronous;
 +            }
 +        }
 +
 +        if (!(options & QQuickPixmap::Asynchronous)) {
 +            bool ok = false;
 +            d = createPixmapDataSync(this, engine, url, requestSize, &ok);
 +            if (ok) {
 +                if (options & QQuickPixmap::Cache)
 +                    d->addToCache();
 +                return;
 +            }
 +            if (d)  // loadable, but encountered error while loading
 +                return;
 +        } 
 +
 +        if (!engine)
 +            return;
 +
 +        d = new QQuickPixmapData(this, url, requestSize);
 +        if (options & QQuickPixmap::Cache)
 +            d->addToCache();
 +
 +        QQuickPixmapReader::readerMutex.lock();
 +        d->reply = QQuickPixmapReader::instance(engine)->getImage(d);
 +        QQuickPixmapReader::readerMutex.unlock();
 +    } else {
 +        d = *iter;
 +        d->addref();
 +        d->declarativePixmaps.insert(this);
 +    }
 +}
 +
 +void QQuickPixmap::clear()
 +{
 +    if (d) {
 +        d->declarativePixmaps.remove(this);
 +        d->release();
 +        d = 0;
 +    }
 +}
 +
 +void QQuickPixmap::clear(QObject *obj)
 +{
 +    if (d) {
 +        if (d->reply) 
 +            QObject::disconnect(d->reply, 0, obj, 0);
 +        d->declarativePixmaps.remove(this);
 +        d->release();
 +        d = 0;
 +    }
 +}
 +
 +bool QQuickPixmap::connectFinished(QObject *object, const char *method)
 +{
 +    if (!d || !d->reply) {
 +        qWarning("QQuickPixmap: connectFinished() called when not loading.");
 +        return false;
 +    }
 +
 +    return QObject::connect(d->reply, SIGNAL(finished()), object, method);
 +}
 +
 +bool QQuickPixmap::connectFinished(QObject *object, int method)
 +{
 +    if (!d || !d->reply) {
 +        qWarning("QQuickPixmap: connectFinished() called when not loading.");
 +        return false;
 +    }
 +
 +    return QMetaObject::connect(d->reply, QQuickPixmapReply::finishedIndex, object, method);
 +}
 +
 +bool QQuickPixmap::connectDownloadProgress(QObject *object, const char *method)
 +{
 +    if (!d || !d->reply) {
 +        qWarning("QQuickPixmap: connectDownloadProgress() called when not loading.");
 +        return false;
 +    }
 +
 +    return QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), object, method);
 +}
 +
 +bool QQuickPixmap::connectDownloadProgress(QObject *object, int method)
 +{
 +    if (!d || !d->reply) {
 +        qWarning("QQuickPixmap: connectDownloadProgress() called when not loading.");
 +        return false;
 +    }
 +
 +    return QMetaObject::connect(d->reply, QQuickPixmapReply::downloadProgressIndex, object, method);
 +}
 +
 +QT_END_NAMESPACE
 +
 +#include <qquickpixmapcache.moc>
index 87d4471,0000000..8462166
mode 100644,000000..100644
--- /dev/null
@@@ -1,798 -1,0 +1,815 @@@
-                                   bool preloadImages)
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include <QStack>
 +#include <QVector>
 +#include <QPainter>
 +#include <QTextLayout>
 +#include <QDebug>
 +#include <qmath.h>
 +#include "qquickstyledtext_p.h"
 +#include <QQmlContext>
 +
 +/*
 +    QQuickStyledText supports few tags:
 +
 +    <b></b> - bold
 +    <strong></strong> - bold
 +    <i></i> - italic
 +    <br> - new line
 +    <p> - paragraph
 +    <u> - underlined text
 +    <font color="color_name" size="1-7"></font>
 +    <h1> to <h6> - headers
 +    <a href=""> - anchor
 +    <ol type="">, <ul type=""> and <li> - ordered and unordered lists
 +    <pre></pre> - preformated
 +    <img src=""> - images
 +
 +    The opening and closing tags must be correctly nested.
 +*/
 +
 +QT_BEGIN_NAMESPACE
 +
++Q_GUI_EXPORT int qt_defaultDpi();
++
 +class QQuickStyledTextPrivate
 +{
 +public:
 +    enum ListType { Ordered, Unordered };
 +    enum ListFormat { Bullet, Disc, Square, Decimal, LowerAlpha, UpperAlpha, LowerRoman, UpperRoman };
 +
 +    struct List {
 +        int level;
 +        ListType type;
 +        ListFormat format;
 +    };
 +
 +    QQuickStyledTextPrivate(const QString &t, QTextLayout &l,
 +                                  QList<QQuickStyledTextImgTag*> &imgTags,
 +                                  const QUrl &baseUrl,
 +                                  QQmlContext *context,
-         , preFormat(false), prependSpace(false), hasSpace(true), preloadImages(preloadImages), context(context)
++                                  bool preloadImages,
++                                  bool *fontSizeModified)
 +        : text(t), layout(l), imgTags(&imgTags), baseFont(layout.font()), baseUrl(baseUrl), hasNewLine(false), nbImages(0), updateImagePositions(false)
++        , preFormat(false), prependSpace(false), hasSpace(true), preloadImages(preloadImages), fontSizeModified(fontSizeModified), context(context)
 +    {
 +    }
 +
 +    void parse();
 +    void appendText(const QString &textIn, int start, int length, QString &textOut);
 +    bool parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format);
 +    bool parseCloseTag(const QChar *&ch, const QString &textIn, QString &textOut);
 +    void parseEntity(const QChar *&ch, const QString &textIn, QString &textOut);
 +    bool parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format);
 +    bool parseOrderedListAttributes(const QChar *&ch, const QString &textIn);
 +    bool parseUnorderedListAttributes(const QChar *&ch, const QString &textIn);
 +    bool parseAnchorAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format);
 +    void parseImageAttributes(const QChar *&ch, const QString &textIn, QString &textOut);
 +    QPair<QStringRef,QStringRef> parseAttribute(const QChar *&ch, const QString &textIn);
 +    QStringRef parseValue(const QChar *&ch, const QString &textIn);
-                                                bool preloadImages)
-     : d(new QQuickStyledTextPrivate(string, layout, imgTags, baseUrl, context, preloadImages))
++    void setFontSize(int size, QTextCharFormat &format);
 +
 +    inline void skipSpace(const QChar *&ch) {
 +        while (ch->isSpace() && !ch->isNull())
 +            ++ch;
 +    }
 +
 +    static QString toAlpha(int value, bool upper);
 +    static QString toRoman(int value, bool upper);
 +
 +    QString text;
 +    QTextLayout &layout;
 +    QList<QQuickStyledTextImgTag*> *imgTags;
 +    QFont baseFont;
 +    QStack<List> listStack;
 +    QUrl baseUrl;
 +    bool hasNewLine;
 +    int nbImages;
 +    bool updateImagePositions;
 +    bool preFormat;
 +    bool prependSpace;
 +    bool hasSpace;
 +    bool preloadImages;
++    bool *fontSizeModified;
 +    QQmlContext *context;
 +
 +    static const QChar lessThan;
 +    static const QChar greaterThan;
 +    static const QChar equals;
 +    static const QChar singleQuote;
 +    static const QChar doubleQuote;
 +    static const QChar slash;
 +    static const QChar ampersand;
 +    static const QChar bullet;
 +    static const QChar disc;
 +    static const QChar square;
 +    static const QChar lineFeed;
 +    static const QChar space;
 +    static const int tabsize = 6;
 +};
 +
 +const QChar QQuickStyledTextPrivate::lessThan(QLatin1Char('<'));
 +const QChar QQuickStyledTextPrivate::greaterThan(QLatin1Char('>'));
 +const QChar QQuickStyledTextPrivate::equals(QLatin1Char('='));
 +const QChar QQuickStyledTextPrivate::singleQuote(QLatin1Char('\''));
 +const QChar QQuickStyledTextPrivate::doubleQuote(QLatin1Char('\"'));
 +const QChar QQuickStyledTextPrivate::slash(QLatin1Char('/'));
 +const QChar QQuickStyledTextPrivate::ampersand(QLatin1Char('&'));
 +const QChar QQuickStyledTextPrivate::bullet(0x2022);
 +const QChar QQuickStyledTextPrivate::disc(0x25e6);
 +const QChar QQuickStyledTextPrivate::square(0x25a1);
 +const QChar QQuickStyledTextPrivate::lineFeed(QLatin1Char('\n'));
 +const QChar QQuickStyledTextPrivate::space(QLatin1Char(' '));
 +
 +QQuickStyledText::QQuickStyledText(const QString &string, QTextLayout &layout,
 +                                               QList<QQuickStyledTextImgTag*> &imgTags,
 +                                               const QUrl &baseUrl,
 +                                               QQmlContext *context,
-                                    bool preloadImages)
++                                               bool preloadImages,
++                                               bool *fontSizeModified)
++    : d(new QQuickStyledTextPrivate(string, layout, imgTags, baseUrl, context, preloadImages, fontSizeModified))
 +{
 +}
 +
 +QQuickStyledText::~QQuickStyledText()
 +{
 +    delete d;
 +}
 +
 +void QQuickStyledText::parse(const QString &string, QTextLayout &layout,
 +                                   QList<QQuickStyledTextImgTag*> &imgTags,
 +                                   const QUrl &baseUrl,
 +                                   QQmlContext *context,
-     QQuickStyledText styledText(string, layout, imgTags, baseUrl, context, preloadImages);
++                                   bool preloadImages,
++                                   bool *fontSizeModified)
 +{
 +    if (string.isEmpty())
 +        return;
-                     static const qreal scaling[] = { 2.0, 1.5, 1.2, 1.0, 0.8, 0.7 };
++    QQuickStyledText styledText(string, layout, imgTags, baseUrl, context, preloadImages, fontSizeModified);
 +    styledText.d->parse();
 +}
 +
 +void QQuickStyledTextPrivate::parse()
 +{
 +    QList<QTextLayout::FormatRange> ranges;
 +    QStack<QTextCharFormat> formatStack;
 +
 +    QString drawText;
 +    drawText.reserve(text.count());
 +
 +    updateImagePositions = !imgTags->isEmpty();
 +
 +    int textStart = 0;
 +    int textLength = 0;
 +    int rangeStart = 0;
 +    bool formatChanged = false;
 +
 +    const QChar *ch = text.constData();
 +    while (!ch->isNull()) {
 +        if (*ch == lessThan) {
 +            if (textLength) {
 +                appendText(text, textStart, textLength, drawText);
 +            } else if (prependSpace) {
 +                drawText.append(space);
 +                prependSpace = false;
 +                hasSpace = true;
 +            }
 +
 +            if (rangeStart != drawText.length() && formatStack.count()) {
 +                if (formatChanged) {
 +                    QTextLayout::FormatRange formatRange;
 +                    formatRange.format = formatStack.top();
 +                    formatRange.start = rangeStart;
 +                    formatRange.length = drawText.length() - rangeStart;
 +                    ranges.append(formatRange);
 +                    formatChanged = false;
 +                } else if (ranges.count()) {
 +                    ranges.last().length += drawText.length() - rangeStart;
 +                }
 +            }
 +            rangeStart = drawText.length();
 +            ++ch;
 +            if (*ch == slash) {
 +                ++ch;
 +                if (parseCloseTag(ch, text, drawText)) {
 +                    if (formatStack.count()) {
 +                        formatChanged = true;
 +                        formatStack.pop();
 +                    }
 +                }
 +            } else {
 +                QTextCharFormat format;
 +                if (formatStack.count())
 +                    format = formatStack.top();
 +                if (parseTag(ch, text, drawText, format)) {
 +                    formatChanged = true;
 +                    formatStack.push(format);
 +                }
 +            }
 +            textStart = ch - text.constData() + 1;
 +            textLength = 0;
 +        } else if (*ch == ampersand) {
 +            ++ch;
 +            appendText(text, textStart, textLength, drawText);
 +            parseEntity(ch, text, drawText);
 +            textStart = ch - text.constData() + 1;
 +            textLength = 0;
 +        } else if (ch->isSpace()) {
 +            if (textLength)
 +                appendText(text, textStart, textLength, drawText);
 +            if (!preFormat) {
 +                prependSpace = !hasSpace;
 +                for (const QChar *n = ch + 1; !n->isNull() && n->isSpace(); ++n)
 +                    ch = n;
 +                hasNewLine = false;
 +            } else  if (*ch == lineFeed) {
 +                drawText.append(QChar(QChar::LineSeparator));
 +                hasNewLine = true;
 +            } else {
 +                drawText.append(QChar(QChar::Nbsp));
 +                hasNewLine = false;
 +            }
 +            textStart = ch - text.constData() + 1;
 +            textLength = 0;
 +        } else {
 +            ++textLength;
 +        }
 +        if (!ch->isNull())
 +            ++ch;
 +    }
 +    if (textLength)
 +        appendText(text, textStart, textLength, drawText);
 +    if (rangeStart != drawText.length() && formatStack.count()) {
 +        if (formatChanged) {
 +            QTextLayout::FormatRange formatRange;
 +            formatRange.format = formatStack.top();
 +            formatRange.start = rangeStart;
 +            formatRange.length = drawText.length() - rangeStart;
 +            ranges.append(formatRange);
 +        } else if (ranges.count()) {
 +            ranges.last().length += drawText.length() - rangeStart;
 +        }
 +    }
 +
 +    layout.setText(drawText);
 +    layout.setAdditionalFormats(ranges);
 +}
 +
 +void QQuickStyledTextPrivate::appendText(const QString &textIn, int start, int length, QString &textOut)
 +{
 +    if (prependSpace)
 +        textOut.append(space);
 +    textOut.append(QStringRef(&textIn, start, length));
 +    prependSpace = false;
 +    hasSpace = false;
 +    hasNewLine = false;
 +}
 +
++//
++// Calculates and sets the correct font size in points
++// depending on the size multiplier and base font.
++//
++void QQuickStyledTextPrivate::setFontSize(int size, QTextCharFormat &format)
++{
++    static const qreal scaling[] = { 0.7, 0.8, 1.0, 1.2, 1.5, 2.0, 2.4 };
++    if (baseFont.pointSizeF() != -1)
++        format.setFontPointSize(baseFont.pointSize() * scaling[size - 1]);
++    else
++        format.setFontPointSize(baseFont.pixelSize() * qreal(72.) / qreal(qt_defaultDpi()) * scaling[size - 1]);
++    *fontSizeModified = true;
++}
++
 +bool QQuickStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn, QString &textOut, QTextCharFormat &format)
 +{
 +    skipSpace(ch);
 +
 +    int tagStart = ch - textIn.constData();
 +    int tagLength = 0;
 +    while (!ch->isNull()) {
 +        if (*ch == greaterThan) {
 +            if (tagLength == 0)
 +                return false;
 +            QStringRef tag(&textIn, tagStart, tagLength);
 +            const QChar char0 = tag.at(0);
 +            if (char0 == QLatin1Char('b')) {
 +                if (tagLength == 1) {
 +                    format.setFontWeight(QFont::Bold);
 +                    return true;
 +                } else if (tagLength == 2 && tag.at(1) == QLatin1Char('r')) {
 +                    textOut.append(QChar(QChar::LineSeparator));
 +                    hasSpace = true;
 +                    prependSpace = false;
 +                    return false;
 +                }
 +            } else if (char0 == QLatin1Char('i')) {
 +                if (tagLength == 1) {
 +                    format.setFontItalic(true);
 +                    return true;
 +                }
 +            } else if (char0 == QLatin1Char('p')) {
 +                if (tagLength == 1) {
 +                    if (!hasNewLine)
 +                        textOut.append(QChar::LineSeparator);
 +                    hasSpace = true;
 +                    prependSpace = false;
 +                } else if (tag == QLatin1String("pre")) {
 +                    preFormat = true;
 +                    if (!hasNewLine)
 +                        textOut.append(QChar::LineSeparator);
 +                    format.setFontFamily(QString::fromLatin1("Courier New,courier"));
 +                    format.setFontFixedPitch(true);
 +                    return true;
 +                }
 +            } else if (char0 == QLatin1Char('u')) {
 +                if (tagLength == 1) {
 +                    format.setFontUnderline(true);
 +                    return true;
 +                } else if (tag == QLatin1String("ul")) {
 +                    List listItem;
 +                    listItem.level = 0;
 +                    listItem.type = Unordered;
 +                    listItem.format = Bullet;
 +                    listStack.push(listItem);
 +                }
 +            } else if (char0 == QLatin1Char('h') && tagLength == 2) {
 +                int level = tag.at(1).digitValue();
 +                if (level >= 1 && level <= 6) {
-                     format.setFontPointSize(baseFont.pointSize() * scaling[level - 1]);
 +                    if (!hasNewLine)
 +                        textOut.append(QChar::LineSeparator);
 +                    hasSpace = true;
 +                    prependSpace = false;
-             if (size >= 1 && size <= 7) {
-                 static const qreal scaling[] = { 0.7, 0.8, 1.0, 1.2, 1.5, 2.0, 2.4 };
-                 format.setFontPointSize(baseFont.pointSize() * scaling[size-1]);
-             }
++                    setFontSize(7 - level, format);
 +                    format.setFontWeight(QFont::Bold);
 +                    return true;
 +                }
 +            } else if (tag == QLatin1String("strong")) {
 +                format.setFontWeight(QFont::Bold);
 +                return true;
 +            } else if (tag == QLatin1String("ol")) {
 +                List listItem;
 +                listItem.level = 0;
 +                listItem.type = Ordered;
 +                listItem.format = Decimal;
 +                listStack.push(listItem);
 +            } else if (tag == QLatin1String("li")) {
 +                if (!hasNewLine)
 +                    textOut.append(QChar(QChar::LineSeparator));
 +                if (!listStack.isEmpty()) {
 +                    int count = ++listStack.top().level;
 +                    for (int i = 0; i < listStack.size(); ++i)
 +                        textOut += QString(tabsize, QChar::Nbsp);
 +                    switch (listStack.top().format) {
 +                    case Decimal:
 +                        textOut += QString::number(count) % QLatin1Char('.');
 +                        break;
 +                    case LowerAlpha:
 +                        textOut += toAlpha(count, false) % QLatin1Char('.');
 +                        break;
 +                    case UpperAlpha:
 +                        textOut += toAlpha(count, true) % QLatin1Char('.');
 +                        break;
 +                    case LowerRoman:
 +                        textOut += toRoman(count, false) % QLatin1Char('.');
 +                        break;
 +                    case UpperRoman:
 +                        textOut += toRoman(count, true) % QLatin1Char('.');
 +                        break;
 +                    case Bullet:
 +                        textOut += bullet;
 +                        break;
 +                    case Disc:
 +                        textOut += disc;
 +                        break;
 +                    case Square:
 +                        textOut += square;
 +                        break;
 +                    }
 +                    textOut += QString(2, QChar::Nbsp);
 +                }
 +            }
 +            return false;
 +        } else if (ch->isSpace()) {
 +            // may have params.
 +            QStringRef tag(&textIn, tagStart, tagLength);
 +            if (tag == QLatin1String("font"))
 +                return parseFontAttributes(ch, textIn, format);
 +            if (tag == QLatin1String("ol")) {
 +                parseOrderedListAttributes(ch, textIn);
 +                return false; // doesn't modify format
 +            }
 +            if (tag == QLatin1String("ul")) {
 +                parseUnorderedListAttributes(ch, textIn);
 +                return false; // doesn't modify format
 +            }
 +            if (tag == QLatin1String("a")) {
 +                return parseAnchorAttributes(ch, textIn, format);
 +            }
 +            if (tag == QLatin1String("img")) {
 +                parseImageAttributes(ch, textIn, textOut);
 +                return false;
 +            }
 +            if (*ch == greaterThan || ch->isNull())
 +                continue;
 +        } else if (*ch != slash) {
 +            tagLength++;
 +        }
 +        ++ch;
 +    }
 +    return false;
 +}
 +
 +bool QQuickStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &textIn, QString &textOut)
 +{
 +    skipSpace(ch);
 +
 +    int tagStart = ch - textIn.constData();
 +    int tagLength = 0;
 +    while (!ch->isNull()) {
 +        if (*ch == greaterThan) {
 +            if (tagLength == 0)
 +                return false;
 +            QStringRef tag(&textIn, tagStart, tagLength);
 +            const QChar char0 = tag.at(0);
 +            hasNewLine = false;
 +            if (char0 == QLatin1Char('b')) {
 +                if (tagLength == 1)
 +                    return true;
 +                else if (tag.at(1) == QLatin1Char('r') && tagLength == 2)
 +                    return false;
 +            } else if (char0 == QLatin1Char('i')) {
 +                if (tagLength == 1)
 +                    return true;
 +            } else if (char0 == QLatin1Char('a')) {
 +                if (tagLength == 1)
 +                    return true;
 +            } else if (char0 == QLatin1Char('p')) {
 +                if (tagLength == 1) {
 +                    textOut.append(QChar::LineSeparator);
 +                    hasNewLine = true;
 +                    hasSpace = true;
 +                    return false;
 +                } else if (tag == QLatin1String("pre")) {
 +                    preFormat = false;
 +                    if (!hasNewLine)
 +                        textOut.append(QChar::LineSeparator);
 +                    hasNewLine = true;
 +                    hasSpace = true;
 +                    return true;
 +                }
 +            } else if (char0 == QLatin1Char('u')) {
 +                if (tagLength == 1)
 +                    return true;
 +                else if (tag == QLatin1String("ul")) {
 +                    if (!listStack.isEmpty()) {
 +                        listStack.pop();
 +                        if (!listStack.count())
 +                            textOut.append(QChar::LineSeparator);
 +                    }
 +                    return false;
 +                }
 +            } else if (char0 == QLatin1Char('h') && tagLength == 2) {
 +                textOut.append(QChar::LineSeparator);
 +                hasNewLine = true;
 +                hasSpace = true;
 +                return true;
 +            } else if (tag == QLatin1String("font")) {
 +                return true;
 +            } else if (tag == QLatin1String("strong")) {
 +                return true;
 +            } else if (tag == QLatin1String("ol")) {
 +                if (!listStack.isEmpty()) {
 +                    listStack.pop();
 +                    if (!listStack.count())
 +                        textOut.append(QChar::LineSeparator);
 +                }
 +                return false;
 +            } else if (tag == QLatin1String("li")) {
 +                return false;
 +            }
 +            return false;
 +        } else if (!ch->isSpace()){
 +            tagLength++;
 +        }
 +        ++ch;
 +    }
 +
 +    return false;
 +}
 +
 +void QQuickStyledTextPrivate::parseEntity(const QChar *&ch, const QString &textIn, QString &textOut)
 +{
 +    int entityStart = ch - textIn.constData();
 +    int entityLength = 0;
 +    while (!ch->isNull()) {
 +        if (*ch == QLatin1Char(';')) {
 +            QStringRef entity(&textIn, entityStart, entityLength);
 +            if (entity == QLatin1String("gt"))
 +                textOut += QChar(62);
 +            else if (entity == QLatin1String("lt"))
 +                textOut += QChar(60);
 +            else if (entity == QLatin1String("amp"))
 +                textOut += QChar(38);
 +            return;
 +        }
 +        ++entityLength;
 +        ++ch;
 +    }
 +}
 +
 +bool QQuickStyledTextPrivate::parseFontAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format)
 +{
 +    bool valid = false;
 +    QPair<QStringRef,QStringRef> attr;
 +    do {
 +        attr = parseAttribute(ch, textIn);
 +        if (attr.first == QLatin1String("color")) {
 +            valid = true;
 +            format.setForeground(QColor(attr.second.toString()));
 +        } else if (attr.first == QLatin1String("size")) {
 +            valid = true;
 +            int size = attr.second.toString().toInt();
 +            if (attr.second.at(0) == QLatin1Char('-') || attr.second.at(0) == QLatin1Char('+'))
 +                size += 3;
++            if (size >= 1 && size <= 7)
++                setFontSize(size, format);
 +        }
 +    } while (!ch->isNull() && !attr.first.isEmpty());
 +
 +    return valid;
 +}
 +
 +bool QQuickStyledTextPrivate::parseOrderedListAttributes(const QChar *&ch, const QString &textIn)
 +{
 +    bool valid = false;
 +
 +    List listItem;
 +    listItem.level = 0;
 +    listItem.type = Ordered;
 +    listItem.format = Decimal;
 +
 +    QPair<QStringRef,QStringRef> attr;
 +    do {
 +        attr = parseAttribute(ch, textIn);
 +        if (attr.first == QLatin1String("type")) {
 +            valid = true;
 +            if (attr.second == QLatin1String("a"))
 +                listItem.format = LowerAlpha;
 +            else if (attr.second == QLatin1String("A"))
 +                listItem.format = UpperAlpha;
 +            else if (attr.second == QLatin1String("i"))
 +                listItem.format = LowerRoman;
 +            else if (attr.second == QLatin1String("I"))
 +                listItem.format = UpperRoman;
 +        }
 +    } while (!ch->isNull() && !attr.first.isEmpty());
 +
 +    listStack.push(listItem);
 +    return valid;
 +}
 +
 +bool QQuickStyledTextPrivate::parseUnorderedListAttributes(const QChar *&ch, const QString &textIn)
 +{
 +    bool valid = false;
 +
 +    List listItem;
 +    listItem.level = 0;
 +    listItem.type = Unordered;
 +    listItem.format = Bullet;
 +
 +    QPair<QStringRef,QStringRef> attr;
 +    do {
 +        attr = parseAttribute(ch, textIn);
 +        if (attr.first == QLatin1String("type")) {
 +            valid = true;
 +            if (attr.second == QLatin1String("disc"))
 +                listItem.format = Disc;
 +            else if (attr.second == QLatin1String("square"))
 +                listItem.format = Square;
 +        }
 +    } while (!ch->isNull() && !attr.first.isEmpty());
 +
 +    listStack.push(listItem);
 +    return valid;
 +}
 +
 +bool QQuickStyledTextPrivate::parseAnchorAttributes(const QChar *&ch, const QString &textIn, QTextCharFormat &format)
 +{
 +    bool valid = false;
 +
 +    QPair<QStringRef,QStringRef> attr;
 +    do {
 +        attr = parseAttribute(ch, textIn);
 +        if (attr.first == QLatin1String("href")) {
 +            format.setAnchorHref(attr.second.toString());
 +            format.setAnchor(true);
 +            format.setFontUnderline(true);
 +            valid = true;
 +        }
 +    } while (!ch->isNull() && !attr.first.isEmpty());
 +
 +    return valid;
 +}
 +
 +void QQuickStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QString &textIn, QString &textOut)
 +{
 +    qreal imgWidth = 0.0;
 +
 +    if (!updateImagePositions) {
 +        QQuickStyledTextImgTag *image = new QQuickStyledTextImgTag;
 +        image->position = textOut.length() + 1;
 +
 +        QPair<QStringRef,QStringRef> attr;
 +        do {
 +            attr = parseAttribute(ch, textIn);
 +            if (attr.first == QLatin1String("src")) {
 +                image->url =  QUrl(attr.second.toString());
 +            } else if (attr.first == QLatin1String("width")) {
 +                image->size.setWidth(attr.second.toString().toInt());
 +            } else if (attr.first == QLatin1String("height")) {
 +                image->size.setHeight(attr.second.toString().toInt());
 +            } else if (attr.first == QLatin1String("align")) {
 +                if (attr.second.toString() == QLatin1String("top")) {
 +                    image->align = QQuickStyledTextImgTag::Top;
 +                } else if (attr.second.toString() == QLatin1String("middle")) {
 +                    image->align = QQuickStyledTextImgTag::Middle;
 +                }
 +            }
 +        } while (!ch->isNull() && !attr.first.isEmpty());
 +
 +        if (preloadImages && !image->size.isValid()) {
 +            // if we don't know its size but the image is a local image,
 +            // we load it in the pixmap cache and save its implicit size
 +            // to avoid a relayout later on.
 +            QUrl url = baseUrl.resolved(image->url);
 +            if (url.isLocalFile()) {
 +                QQuickPixmap *pix = new QQuickPixmap(context->engine(), url, image->size);
 +                if (pix && pix->isReady()) {
 +                    image->size = pix->implicitSize();
 +                    image->pix = pix;
 +                }
 +            }
 +        }
 +
 +        imgWidth = image->size.width();
 +        imgTags->append(image);
 +
 +    } else {
 +        // if we already have a list of img tags for this text
 +        // we only want to update the positions of these tags.
 +        QQuickStyledTextImgTag *image = imgTags->value(nbImages);
 +        image->position = textOut.length() + 1;
 +        imgWidth = image->size.width();
 +        QPair<QStringRef,QStringRef> attr;
 +        do {
 +            attr = parseAttribute(ch, textIn);
 +        } while (!ch->isNull() && !attr.first.isEmpty());
 +        nbImages++;
 +    }
 +
 +    QFontMetricsF fm(layout.font());
 +    QString padding(qFloor(imgWidth / fm.width(QChar::Nbsp)), QChar::Nbsp);
 +    textOut += QLatin1Char(' ');
 +    textOut += padding;
 +    textOut += QLatin1Char(' ');
 +}
 +
 +QPair<QStringRef,QStringRef> QQuickStyledTextPrivate::parseAttribute(const QChar *&ch, const QString &textIn)
 +{
 +    skipSpace(ch);
 +
 +    int attrStart = ch - textIn.constData();
 +    int attrLength = 0;
 +    while (!ch->isNull()) {
 +        if (*ch == greaterThan) {
 +            break;
 +        } else if (*ch == equals) {
 +            ++ch;
 +            if (*ch != singleQuote && *ch != doubleQuote) {
 +                while (*ch != greaterThan && !ch->isNull())
 +                    ++ch;
 +                break;
 +            }
 +            ++ch;
 +            if (!attrLength)
 +                break;
 +            QStringRef attr(&textIn, attrStart, attrLength);
 +            QStringRef val = parseValue(ch, textIn);
 +            if (!val.isEmpty())
 +                return QPair<QStringRef,QStringRef>(attr,val);
 +            break;
 +        } else {
 +            ++attrLength;
 +        }
 +        ++ch;
 +    }
 +
 +    return QPair<QStringRef,QStringRef>();
 +}
 +
 +QStringRef QQuickStyledTextPrivate::parseValue(const QChar *&ch, const QString &textIn)
 +{
 +    int valStart = ch - textIn.constData();
 +    int valLength = 0;
 +    while (*ch != singleQuote && *ch != doubleQuote && !ch->isNull()) {
 +        ++valLength;
 +        ++ch;
 +    }
 +    if (ch->isNull())
 +        return QStringRef();
 +    ++ch; // skip quote
 +
 +    return QStringRef(&textIn, valStart, valLength);
 +}
 +
 +QString QQuickStyledTextPrivate::toAlpha(int value, bool upper)
 +{
 +    const char baseChar = upper ? 'A' : 'a';
 +
 +    QString result;
 +    int c = value;
 +    while (c > 0) {
 +        c--;
 +        result.prepend(QChar(baseChar + (c % 26)));
 +        c /= 26;
 +    }
 +    return result;
 +}
 +
 +QString QQuickStyledTextPrivate::toRoman(int value, bool upper)
 +{
 +    QString result = QLatin1String("?");
 +    // works for up to 4999 items
 +    if (value < 5000) {
 +        QByteArray romanNumeral;
 +
 +        static const char romanSymbolsLower[] = "iiivixxxlxcccdcmmmm";
 +        static const char romanSymbolsUpper[] = "IIIVIXXXLXCCCDCMMMM";
 +        QByteArray romanSymbols;
 +        if (!upper)
 +            romanSymbols = QByteArray::fromRawData(romanSymbolsLower, sizeof(romanSymbolsLower));
 +        else
 +            romanSymbols = QByteArray::fromRawData(romanSymbolsUpper, sizeof(romanSymbolsUpper));
 +
 +        int c[] = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };
 +        int n = value;
 +        for (int i = 12; i >= 0; n %= c[i], i--) {
 +            int q = n / c[i];
 +            if (q > 0) {
 +                int startDigit = i + (i + 3) / 4;
 +                int numDigits;
 +                if (i % 4) {
 +                    if ((i - 2) % 4)
 +                        numDigits = 2;
 +                    else
 +                        numDigits = 1;
 +                }
 +                else
 +                    numDigits = q;
 +                romanNumeral.append(romanSymbols.mid(startDigit, numDigits));
 +            }
 +        }
 +        result = QString::fromLatin1(romanNumeral);
 +    }
 +    return result;
 +}
 +
 +QT_END_NAMESPACE
index bfc7ffe,0000000..4e0f9ea
mode 100644,000000..100644
--- /dev/null
@@@ -1,103 -1,0 +1,105 @@@
-                       bool preloadImages);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQUICKSTYLEDTEXT_H
 +#define QQUICKSTYLEDTEXT_H
 +
 +#include <QSize>
 +#include <QPointF>
 +#include <QList>
 +#include <QUrl>
 +#include <QtQuick/private/qquickpixmapcache_p.h>
 +
 +QT_BEGIN_NAMESPACE
 +
 +class QQuickStyledTextImgTag;
 +class QQuickStyledTextPrivate;
 +class QString;
 +class QQmlContext;
 +
 +class Q_AUTOTEST_EXPORT QQuickStyledTextImgTag
 +{
 +public:
 +    QQuickStyledTextImgTag()
 +        : position(0), align(QQuickStyledTextImgTag::Bottom), pix(0)
 +    { }
 +
 +    ~QQuickStyledTextImgTag() { delete pix; }
 +
 +    enum Align {
 +        Bottom,
 +        Middle,
 +        Top
 +    };
 +
 +    QUrl url;
 +    QPointF pos;
 +    QSize size;
 +    int position;
 +    Align align;
 +    QQuickPixmap *pix;
 +};
 +
 +class Q_AUTOTEST_EXPORT QQuickStyledText
 +{
 +public:
 +    static void parse(const QString &string, QTextLayout &layout,
 +                      QList<QQuickStyledTextImgTag*> &imgTags,
 +                      const QUrl &baseUrl,
 +                      QQmlContext *context,
-                            bool preloadImages);
++                      bool preloadImages,
++                      bool *fontSizeModified);
 +
 +private:
 +    QQuickStyledText(const QString &string, QTextLayout &layout,
 +                           QList<QQuickStyledTextImgTag*> &imgTags,
 +                           const QUrl &baseUrl,
 +                           QQmlContext *context,
++                           bool preloadImages,
++                           bool *fontSizeModified);
 +    ~QQuickStyledText();
 +
 +    QQuickStyledTextPrivate *d;
 +};
 +
 +QT_END_NAMESPACE
 +
 +#endif
@@@ -1,4 -1,4 +1,9 @@@
  TEMPLATE=subdirs
--SUBDIRS=\
--           headersclean \
++
++# FIXME
++# This test is crrently broken:
++#SUBDIRS=\
++           #headersclean \
++
++SUBDIRS=
  
index 0d11213,0000000..81fe3d5
mode 100644,000000..100644
--- /dev/null
@@@ -1,15 -1,0 +1,15 @@@
- QT += qml-private testlib
 +CONFIG += testcase
 +TARGET = tst_qqmlprofilerservice
 +macx:CONFIG -= app_bundle
 +
 +HEADERS += ../shared/debugutil_p.h
 +
 +SOURCES += tst_qqmlprofilerservice.cpp \
 +           ../shared/debugutil.cpp
 +OTHER_FILES += data/test.qml
 +
 +include (../../../shared/util.pri)
 +
 +CONFIG += parallel_test declarative_debug
 +
++QT += core-private v8-private qml-private testlib
index a2cac08,0000000..c5992a4
mode 100644,000000..100644
--- /dev/null
@@@ -1,280 -1,0 +1,294 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include <qtest.h>
 +#include <QLibraryInfo>
 +
 +#include "QtQml/private/qv8profilerservice_p.h"
 +#include "../shared/debugutil_p.h"
 +#include "../../../shared/util.h"
 +
 +#define PORT 13774
 +#define STR_PORT "13774"
 +
 +class QV8ProfilerClient : public QQmlDebugClient
 +{
 +    Q_OBJECT
 +
 +public:
 +    QV8ProfilerClient(QQmlDebugConnection *connection)
 +        : QQmlDebugClient(QLatin1String("V8Profiler"), connection)
 +    {
 +    }
 +
 +    void startProfiling(const QString &name) {
 +        QByteArray message;
 +        QDataStream stream(&message, QIODevice::WriteOnly);
 +        stream << QByteArray("V8PROFILER") << QByteArray("start") << name;
 +        sendMessage(message);
 +    }
 +
 +    void stopProfiling(const QString &name) {
 +        QByteArray message;
 +        QDataStream stream(&message, QIODevice::WriteOnly);
 +        stream << QByteArray("V8PROFILER") << QByteArray("stop") << name;
 +        sendMessage(message);
 +    }
 +
 +    void takeSnapshot() {
 +        QByteArray message;
 +        QDataStream stream(&message, QIODevice::WriteOnly);
 +        stream << QByteArray("V8SNAPSHOT") << QByteArray("full");
 +        sendMessage(message);
 +    }
 +
 +    void deleteSnapshots() {
 +        QByteArray message;
 +        QDataStream stream(&message, QIODevice::WriteOnly);
 +        stream << QByteArray("V8SNAPSHOT") << QByteArray("delete");
 +        sendMessage(message);
 +    }
 +
 +    QList<QV8ProfilerData> traceMessages;
 +    QList<QByteArray> snapshotMessages;
 +
 +signals:
++    void started();
 +    void complete();
 +    void snapshot();
 +
 +protected:
 +    void messageReceived(const QByteArray &message);
 +};
 +
 +class tst_QV8ProfilerService : public QQmlDataTest
 +{
 +    Q_OBJECT
 +
 +public:
 +    tst_QV8ProfilerService()
 +        : m_process(0)
 +        , m_connection(0)
 +        , m_client(0)
 +    {
 +    }
 +
 +private:
 +    QQmlDebugProcess *m_process;
 +    QQmlDebugConnection *m_connection;
 +    QV8ProfilerClient *m_client;
 +
 +    void connect(bool block, const QString &testFile);
 +
 +private slots:
 +    void cleanup();
 +
 +    void blockingConnectWithTraceEnabled();
 +    void blockingConnectWithTraceDisabled();
 +    void nonBlockingConnect();
 +    void snapshot();
 +    void profileOnExit();
 +    void console();
 +};
 +
 +void QV8ProfilerClient::messageReceived(const QByteArray &message)
 +{
 +    QByteArray msg = message;
 +    QDataStream stream(&msg, QIODevice::ReadOnly);
 +
 +    int messageType;
 +    stream >> messageType;
 +
 +    QVERIFY(messageType >= 0);
 +    QVERIFY(messageType < QV8ProfilerService::V8MaximumMessage);
 +
 +    switch (messageType) {
 +    case QV8ProfilerService::V8Entry: {
 +        QV8ProfilerData entry;
 +        stream >> entry.filename >> entry.functionname >> entry.lineNumber >> entry.totalTime >> entry.selfTime >> entry.treeLevel;
 +        traceMessages.append(entry);
 +        break;
 +    }
 +    case QV8ProfilerService::V8Complete:
 +        emit complete();
 +        break;
 +    case QV8ProfilerService::V8SnapshotChunk: {
 +        QByteArray json;
 +        stream >> json;
 +        snapshotMessages.append(json);
 +        break;
 +    }
 +    case QV8ProfilerService::V8SnapshotComplete:
 +        emit snapshot();
 +        break;
++    case QV8ProfilerService::V8Started:
++        emit started();
++        break;
 +    default:
 +        QString failMessage = QString("Unknown message type: %1").arg(messageType);
 +        QFAIL(qPrintable(failMessage));
 +    }
 +
 +    QVERIFY(stream.atEnd());
 +}
 +
 +void tst_QV8ProfilerService::connect(bool block, const QString &testFile)
 +{
 +    const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene";
 +    QStringList arguments;
 +
 +    if (block)
 +        arguments << QString("-qmljsdebugger=port:"STR_PORT",block");
 +    else
 +        arguments << QString("-qmljsdebugger=port:"STR_PORT);
 +
 +    arguments << QQmlDataTest::instance()->testFile(testFile);
 +
 +    m_process = new QQmlDebugProcess(executable);
 +    m_process->start(QStringList() << arguments);
 +    if (!m_process->waitForSessionStart()) {
 +        QString failMsg = QString("Could not launch app '%1'.\nApplication output:\n%2").arg(
 +                    executable, m_process->output());
 +        QFAIL(qPrintable(failMsg));
 +    }
 +
 +    QQmlDebugConnection *m_connection = new QQmlDebugConnection();
 +    m_client = new QV8ProfilerClient(m_connection);
 +
 +    m_connection->connectToHost(QLatin1String("127.0.0.1"), PORT);
 +}
 +
 +void tst_QV8ProfilerService::cleanup()
 +{
 +    if (QTest::currentTestFailed())
 +        qDebug() << "Application Output:" << m_process->output();
 +
 +    delete m_process;
 +    delete m_connection;
 +    delete m_client;
 +}
 +
 +void tst_QV8ProfilerService::blockingConnectWithTraceEnabled()
 +{
 +    connect(true, "test.qml");
 +    QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
 +
 +    m_client->startProfiling("");
++    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(started())),
++             "No start signal received in time.");
 +    m_client->stopProfiling("");
 +    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
 +             "No trace received in time.");
 +}
 +
 +void tst_QV8ProfilerService::blockingConnectWithTraceDisabled()
 +{
 +    connect(true, "test.qml");
 +    QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
 +
 +    m_client->stopProfiling("");
 +    if (QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete()), 1000)) {
 +        QString failMsg
 +                = QString("Unexpected trace received! App output: %1\n\n").arg(m_process->output());
 +        QFAIL(qPrintable(failMsg));
 +    }
 +    m_client->startProfiling("");
++    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(started())),
++             "No start signal received in time.");
 +    m_client->stopProfiling("");
 +    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
 +             "No trace received in time.");
 +}
 +
 +void tst_QV8ProfilerService::nonBlockingConnect()
 +{
 +    connect(false, "test.qml");
 +    QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
 +
 +    m_client->startProfiling("");
++    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(started())),
++             "No start signal received in time.");
 +    m_client->stopProfiling("");
 +    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
 +             "No trace received in time.");
 +}
 +
 +void tst_QV8ProfilerService::snapshot()
 +{
 +    connect(false, "test.qml");
 +    QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
 +
 +    m_client->takeSnapshot();
 +    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(snapshot())),
 +             "No trace received in time.");
 +}
 +
 +void tst_QV8ProfilerService::profileOnExit()
 +{
 +    connect(true, "exit.qml");
 +    QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
 +
 +    m_client->startProfiling("");
++    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(started())),
++             "No start signal received in time.");
 +
 +    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
 +             "No trace received in time.");
 +    //QVERIFY(!m_client->traceMessages.isEmpty());
 +}
 +
 +void tst_QV8ProfilerService::console()
 +{
 +    connect(true, "console.qml");
 +    QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
 +
 +    m_client->stopProfiling("");
 +
++    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(started())),
++             "No start signal received in time.");
 +    QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
 +             "No trace received in time.");
 +    QVERIFY(!m_client->traceMessages.isEmpty());
 +}
 +
 +QTEST_MAIN(tst_QV8ProfilerService)
 +
 +#include "tst_qv8profilerservice.moc"
index 7a62a71,0000000..bcfbcbd
mode 100644,000000..100644
--- /dev/null
@@@ -1,55 -1,0 +1,56 @@@
 +TEMPLATE = subdirs
 +
 +METATYPETESTS += \
 +    qqmlmetatype
 +
 +PUBLICTESTS += \
 +    parserstress \
 +    qjsengine \
 +    qjsvalue \
 +    qjsvalueiterator \
 +    qmlmin \
 +    qmlplugindump \
 +    qqmlcomponent \
 +    qqmlconsole \
 +    qqmlcontext \
 +    qqmlengine \
 +    qqmlerror \
 +    qqmlincubator \
 +    qqmlinfo \
 +    qqmllistreference \
 +    qqmllocale \
++    qqmlmetaobject \
 +    qqmlmoduleplugin \
 +    qqmlqt \
 +    qqmltranslation \
 +    qqmlxmlhttprequest \
 +    qqmlparser \
 +    qquickfolderlistmodel
 +
 +PRIVATETESTS += \
 +    animation \
 +    qqmlcpputils \
 +    qqmlecmascript \
 +    qqmlexpression \
 +    qqmlimageprovider \
 +    qqmlinstruction \
 +    qqmllanguage \
 +    qqmlproperty \
 +    qqmlpropertymap \
 +    qqmlsqldatabase \
 +    qqmlvaluetypes \
 +    qquickbinding \
 +    qquickchangeset \
 +    qquickconnection \
 +    qquicklistcompositor \
 +    qquicklistmodel \
 +    qquickworkerscript \
 +    v4
 +
 +SUBDIRS += $$PUBLICTESTS
 +SUBDIRS += $$METATYPETESTS
 +SUBDIRS += debugger
 +
 +contains(QT_CONFIG, private_tests) {
 +    SUBDIRS += $$PRIVATETESTS
 +}
index 2d76431,0000000..dfc88fb
mode 100644,000000..100644
--- /dev/null
@@@ -1,192 -1,0 +1,193 @@@
-     invalidFiles << "tests/auto/qml/qqmllanguage/data/signal.2.qml";
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include <qtest.h>
 +#include <QLibraryInfo>
 +#include <QDir>
 +#include <QProcess>
 +#include <QDebug>
 +#include <QQmlError>
 +#include <cstdlib>
 +
 +class tst_qmlmin : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    tst_qmlmin();
 +
 +private slots:
 +    void initTestCase();
 +    void qmlMinify_data();
 +    void qmlMinify();
 +
 +private:
 +    QString qmlminPath;
 +    QStringList excludedDirs;
 +    QStringList invalidFiles;
 +
 +    QStringList findFiles(const QDir &);
 +    bool isInvalidFile(const QFileInfo &fileName) const;
 +};
 +
 +tst_qmlmin::tst_qmlmin()
 +{
 +}
 +
 +void tst_qmlmin::initTestCase()
 +{
 +    qmlminPath = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/qmlmin");
 +#ifdef Q_OS_WIN
 +    qmlminPath += QLatin1String(".exe");
 +#endif
 +    if (!QFileInfo(qmlminPath).exists()) {
 +        QString message = QString::fromLatin1("qmlmin executable not found (looked for %0)")
 +                .arg(qmlminPath);
 +        QFAIL(qPrintable(message));
 +    }
 +
 +    // Add directories you want excluded here
 +
 +    // These snippets are not expected to run on their own.
 +    excludedDirs << "doc/src/snippets/qml/visualdatamodel_rootindex";
 +    excludedDirs << "doc/src/snippets/qml/qtbinding";
 +    excludedDirs << "doc/src/snippets/qml/imports";
 +    excludedDirs << "doc/src/snippets/qtquick1/visualdatamodel_rootindex";
 +    excludedDirs << "doc/src/snippets/qtquick1/qtbinding";
 +    excludedDirs << "doc/src/snippets/qtquick1/imports";
 +
 +    // Add invalid files (i.e. files with syntax errors)
 +    invalidFiles << "tests/auto/quick/qquickloader/data/InvalidSourceComponent.qml";
 +    invalidFiles << "tests/auto/qml/qqmllanguage/data/dynamicObjectProperties.2.qml";
++    invalidFiles << "tests/auto/qml/qqmllanguage/data/signal.2.qml";
 +    invalidFiles << "tests/auto/qml/qqmllanguage/data/signal.3.qml";
++    invalidFiles << "tests/auto/qml/qqmllanguage/data/signal.5.qml";
 +    invalidFiles << "tests/auto/qml/qqmllanguage/data/property.4.qml";
 +    invalidFiles << "tests/auto/qml/qqmllanguage/data/empty.qml";
 +    invalidFiles << "tests/auto/qml/qqmllanguage/data/missingObject.qml";
 +    invalidFiles << "tests/auto/qml/qqmllanguage/data/insertedSemicolon.1.qml";
 +    invalidFiles << "tests/auto/qml/qqmllanguage/data/nonexistantProperty.5.qml";
 +    invalidFiles << "tests/auto/qml/qqmllanguage/data/invalidRoot.1.qml";
 +    invalidFiles << "tests/auto/qml/qquickfolderlistmodel/data/dummy.qml";
 +    invalidFiles << "tests/auto/qml/qqmlecmascript/data/qtbug_22843.js";
 +    invalidFiles << "tests/auto/qml/qqmlecmascript/data/qtbug_22843.library.js";
 +    invalidFiles << "tests/auto/qml/qquickworkerscript/data/script_error_onLoad.js";
 +    invalidFiles << "tests/auto/qml/parserstress/tests/ecma_3/Unicode/regress-352044-02-n.js";
 +}
 +
 +QStringList tst_qmlmin::findFiles(const QDir &d)
 +{
 +    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
 +        QString s = excludedDirs.at(ii);
 +        if (d.absolutePath().endsWith(s))
 +            return QStringList();
 +    }
 +
 +    QStringList rv;
 +
 +    QStringList files = d.entryList(QStringList() << QLatin1String("*.qml") << QLatin1String("*.js"),
 +                                    QDir::Files);
 +    foreach (const QString &file, files) {
 +        rv << d.absoluteFilePath(file);
 +    }
 +
 +    QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
 +                                   QDir::NoSymLinks);
 +    foreach (const QString &dir, dirs) {
 +        QDir sub = d;
 +        sub.cd(dir);
 +        rv << findFiles(sub);
 +    }
 +
 +    return rv;
 +}
 +
 +bool tst_qmlmin::isInvalidFile(const QFileInfo &fileName) const
 +{
 +    foreach (const QString &invalidFile, invalidFiles) {
 +        if (fileName.absoluteFilePath().endsWith(invalidFile))
 +            return true;
 +    }
 +    return false;
 +}
 +
 +/*
 +This test runs all the examples in the QtQml UI source tree and ensures
 +that they start and exit cleanly.
 +
 +Examples are any .qml files under the examples/ directory that start
 +with a lower case letter.
 +*/
 +
 +void tst_qmlmin::qmlMinify_data()
 +{
 +    QTest::addColumn<QString>("file");
 +
 +    QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";
 +    QString tests = QLatin1String(SRCDIR) + "/../../../../tests/";
 +
 +    QStringList files;
 +    files << findFiles(QDir(examples));
 +    files << findFiles(QDir(tests));
 +
 +    foreach (const QString &file, files)
 +        QTest::newRow(qPrintable(file)) << file;
 +}
 +
 +void tst_qmlmin::qmlMinify()
 +{
 +    QFETCH(QString, file);
 +
 +    QProcess qmlminify;
 +    qmlminify.start(qmlminPath, QStringList() << QLatin1String("--verify-only") << file);
 +    qmlminify.waitForFinished();
 +
 +    QCOMPARE(qmlminify.error(), QProcess::UnknownError);
 +    QCOMPARE(qmlminify.exitStatus(), QProcess::NormalExit);
 +
 +    if (isInvalidFile(file))
 +        QCOMPARE(qmlminify.exitCode(), EXIT_FAILURE); // cannot minify files with syntax errors
 +    else
 +        QCOMPARE(qmlminify.exitCode(), 0);
 +}
 +
 +QTEST_MAIN(tst_qmlmin)
 +
 +#include "tst_qmlmin.moc"
index d277952,0000000..603c091
mode 100644,000000..100644
--- /dev/null
@@@ -1,186 -1,0 +1,218 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <qtest.h>
 +#include <QDebug>
 +
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtQml/qqmlproperty.h>
 +#include <QtQml/qqmlincubator.h>
 +#include <qcolor.h>
 +#include "../../shared/util.h"
 +
 +class MyIC : public QObject, public QQmlIncubationController
 +{
 +    Q_OBJECT
 +public:
 +    MyIC() { startTimer(5); }
 +protected:
 +    virtual void timerEvent(QTimerEvent*) {
 +        incubateFor(5);
 +    }
 +};
 +
 +class tst_qqmlcomponent : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_qqmlcomponent() { engine.setIncubationController(&ic); }
 +
 +private slots:
 +    void null();
 +    void loadEmptyUrl();
 +    void qmlCreateObject();
 +    void qmlCreateObjectWithProperties();
 +    void qmlIncubateObject();
++    void qmlCreateParentReference();
 +
 +private:
 +    QQmlEngine engine;
 +    MyIC ic;
 +};
 +
 +void tst_qqmlcomponent::null()
 +{
 +    {
 +        QQmlComponent c;
 +        QVERIFY(c.isNull());
 +    }
 +
 +    {
 +        QQmlComponent c(&engine);
 +        QVERIFY(c.isNull());
 +    }
 +}
 +
 +
 +void tst_qqmlcomponent::loadEmptyUrl()
 +{
 +    QQmlComponent c(&engine);
 +    c.loadUrl(QUrl());
 +
 +    QVERIFY(c.isError());
 +    QCOMPARE(c.errors().count(), 1);
 +    QQmlError error = c.errors().first();
 +    QCOMPARE(error.url(), QUrl());
 +    QCOMPARE(error.line(), -1);
 +    QCOMPARE(error.column(), -1);
 +    QCOMPARE(error.description(), QLatin1String("Invalid empty URL"));
 +}
 +
 +void tst_qqmlcomponent::qmlIncubateObject()
 +{
 +    QQmlComponent component(&engine, testFileUrl("incubateObject.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->property("test1").toBool(), true);
 +    QCOMPARE(object->property("test2").toBool(), false);
 +
 +    QTRY_VERIFY(object->property("test2").toBool() == true);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlcomponent::qmlCreateObject()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, testFileUrl("createObject.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QObject *testObject1 = object->property("qobject").value<QObject*>();
 +    QVERIFY(testObject1);
 +    QVERIFY(testObject1->parent() == object);
 +
 +    QObject *testObject2 = object->property("declarativeitem").value<QObject*>();
 +    QVERIFY(testObject2);
 +    QVERIFY(testObject2->parent() == object);
 +    QCOMPARE(testObject2->metaObject()->className(), "QQuickItem");
 +}
 +
 +void tst_qqmlcomponent::qmlCreateObjectWithProperties()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, testFileUrl("createObjectWithScript.qml"));
 +    QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8());
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QObject *testObject1 = object->property("declarativerectangle").value<QObject*>();
 +    QVERIFY(testObject1);
 +    QVERIFY(testObject1->parent() == object);
 +    QCOMPARE(testObject1->property("x").value<int>(), 17);
 +    QCOMPARE(testObject1->property("y").value<int>(), 17);
 +    QCOMPARE(testObject1->property("color").value<QColor>(), QColor(255,255,255));
 +    QCOMPARE(QQmlProperty::read(testObject1,"border.width").toInt(), 3);
 +    QCOMPARE(QQmlProperty::read(testObject1,"innerRect.border.width").toInt(), 20);
 +    delete testObject1;
 +
 +    QObject *testObject2 = object->property("declarativeitem").value<QObject*>();
 +    QVERIFY(testObject2);
 +    QVERIFY(testObject2->parent() == object);
 +    //QCOMPARE(testObject2->metaObject()->className(), "QDeclarativeItem_QML_2");
 +    QCOMPARE(testObject2->property("x").value<int>(), 17);
 +    QCOMPARE(testObject2->property("y").value<int>(), 17);
 +    QCOMPARE(testObject2->property("testBool").value<bool>(), true);
 +    QCOMPARE(testObject2->property("testInt").value<int>(), 17);
 +    QCOMPARE(testObject2->property("testObject").value<QObject*>(), object);
 +    delete testObject2;
 +
 +    QObject *testBindingObj = object->property("bindingTestObject").value<QObject*>();
 +    QVERIFY(testBindingObj);
 +    QCOMPARE(testBindingObj->parent(), object);
 +    QCOMPARE(testBindingObj->property("testValue").value<int>(), 300);
 +    object->setProperty("width", 150);
 +    QCOMPARE(testBindingObj->property("testValue").value<int>(), 150 * 3);
 +    delete testBindingObj;
 +
 +    QObject *testBindingThisObj = object->property("bindingThisTestObject").value<QObject*>();
 +    QVERIFY(testBindingThisObj);
 +    QCOMPARE(testBindingThisObj->parent(), object);
 +    QCOMPARE(testBindingThisObj->property("testValue").value<int>(), 900);
 +    testBindingThisObj->setProperty("width", 200);
 +    QCOMPARE(testBindingThisObj->property("testValue").value<int>(), 200 * 3);
 +    delete testBindingThisObj;
 +}
 +
++static QStringList warnings;
++static void msgHandler(QtMsgType, const char *warning)
++{
++    warnings << QString::fromUtf8(warning);
++}
++
++void tst_qqmlcomponent::qmlCreateParentReference()
++{
++    QQmlEngine engine;
++
++    QCOMPARE(engine.outputWarningsToStandardError(), true);
++
++    warnings.clear();
++    QtMsgHandler old = qInstallMsgHandler(msgHandler);
++
++    QQmlComponent component(&engine, testFileUrl("createParentReference.qml"));
++    QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8());
++    QObject *object = component.create();
++    QVERIFY(object != 0);
++
++    QVERIFY(QMetaObject::invokeMethod(object, "createChild"));
++    delete object;
++
++    qInstallMsgHandler(old);
++
++    engine.setOutputWarningsToStandardError(false);
++    QCOMPARE(engine.outputWarningsToStandardError(), false);
++
++    QCOMPARE(warnings.count(), 0);
++}
++
 +QTEST_MAIN(tst_qqmlcomponent)
 +
 +#include "tst_qqmlcomponent.moc"
index 154e6f0,0000000..1d68e8a
mode 100644,000000..100644
--- /dev/null
@@@ -1,1311 -1,0 +1,1313 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#ifndef TESTTYPES_H
 +#define TESTTYPES_H
 +
 +#include <QtCore/qobject.h>
 +#include <QtQml/qqml.h>
 +#include <QtQml/qqmlexpression.h>
 +#include <QtCore/qpoint.h>
 +#include <QtCore/qsize.h>
 +#include <QtQml/qqmllist.h>
 +#include <QtCore/qrect.h>
 +#include <QtGui/qmatrix.h>
 +#include <QtGui/qcolor.h>
 +#include <QtGui/qvector3d.h>
 +#include <QtGui/QPixmap>
 +#include <QtCore/qdatetime.h>
 +#include <QtQml/qjsvalue.h>
 +#include <QtQml/qqmlscriptstring.h>
 +#include <QtQml/qqmlcomponent.h>
 +
 +#include <private/qqmlengine_p.h>
 +#include <private/qv8engine_p.h>
 +
 +class MyQmlAttachedObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value CONSTANT)
 +    Q_PROPERTY(int value2 READ value2 WRITE setValue2 NOTIFY value2Changed)
 +public:
 +    MyQmlAttachedObject(QObject *parent) : QObject(parent), m_value2(0) {}
 +
 +    int value() const { return 19; }
 +    int value2() const { return m_value2; }
 +    void setValue2(int v) { if (m_value2 == v) return; m_value2 = v; emit value2Changed(); }
 +
 +    void emitMySignal() { emit mySignal(); }
 +
 +signals:
 +    void value2Changed();
 +    void mySignal();
 +
 +private:
 +    int m_value2;
 +};
 +
 +class MyQmlObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_ENUMS(MyEnum)
 +    Q_ENUMS(MyEnum2)
 +    Q_PROPERTY(int deleteOnSet READ deleteOnSet WRITE setDeleteOnSet)
 +    Q_PROPERTY(bool trueProperty READ trueProperty CONSTANT)
 +    Q_PROPERTY(bool falseProperty READ falseProperty CONSTANT)
 +    Q_PROPERTY(int value READ value WRITE setValue)
 +    Q_PROPERTY(int console READ console CONSTANT)
 +    Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringChanged)
 +    Q_PROPERTY(QUrl urlProperty READ urlProperty WRITE setUrlProperty NOTIFY urlChanged)
 +    Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty NOTIFY objectChanged)
 +    Q_PROPERTY(QQmlListProperty<QObject> objectListProperty READ objectListProperty CONSTANT)
 +    Q_PROPERTY(int resettableProperty READ resettableProperty WRITE setResettableProperty RESET resetProperty)
 +    Q_PROPERTY(QRegExp regExp READ regExp WRITE setRegExp)
 +    Q_PROPERTY(int nonscriptable READ nonscriptable WRITE setNonscriptable SCRIPTABLE false)
 +    Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty NOTIFY intChanged)
 +
 +public:
 +    MyQmlObject(): myinvokableObject(0), m_methodCalled(false), m_methodIntCalled(false), m_object(0), m_value(0), m_resetProperty(13), m_intProperty(0) {}
 +
 +    enum MyEnum { EnumValue1 = 0, EnumValue2 = 1 };
 +    enum MyEnum2 { EnumValue3 = 2, EnumValue4 = 3 };
 +
 +    bool trueProperty() const { return true; }
 +    bool falseProperty() const { return false; }
 +
 +    QString stringProperty() const { return m_string; }
 +    void setStringProperty(const QString &s)
 +    {
 +        if (s == m_string)
 +            return;
 +        m_string = s;
 +        emit stringChanged();
 +    }
 +
 +    QUrl urlProperty() const { return m_url; }
 +    void setUrlProperty(const QUrl &url)
 +    {
 +        if (url == m_url)
 +            return;
 +        m_url = url;
 +        emit urlChanged();
 +    }
 +
 +    QObject *objectProperty() const { return m_object; }
 +    void setObjectProperty(QObject *obj) { 
 +        if (obj == m_object)
 +            return;
 +        m_object = obj;
 +        emit objectChanged();
 +    }
 +
 +    QQmlListProperty<QObject> objectListProperty() { return QQmlListProperty<QObject>(this, m_objectQList); }
 +
 +    bool methodCalled() const { return m_methodCalled; }
 +    bool methodIntCalled() const { return m_methodIntCalled; }
 +
 +    QString string() const { return m_string; }
 +
 +    static MyQmlAttachedObject *qmlAttachedProperties(QObject *o) {
 +        return new MyQmlAttachedObject(o);
 +    }
 +
 +    int deleteOnSet() const { return 1; }
 +    void setDeleteOnSet(int v) { if(v) delete this; }
 +
 +    int value() const { return m_value; }
 +    void setValue(int v) { m_value = v; }
 +
 +    int resettableProperty() const { return m_resetProperty; }
 +    void setResettableProperty(int v) { m_resetProperty = v; }
 +    void resetProperty() { m_resetProperty = 13; }
 +
 +    QRegExp regExp() { return m_regExp; }
 +    void setRegExp(const QRegExp &regExp) { m_regExp = regExp; }
 +
 +    int console() const { return 11; }
 +
 +    int nonscriptable() const { return 0; }
 +    void setNonscriptable(int) {}
 +
 +    MyQmlObject *myinvokableObject;
 +    Q_INVOKABLE MyQmlObject *returnme() { return this; }
 +
 +    struct MyType {
 +        int value;
 +    };
 +    QVariant variant() const { return m_variant; }
 +    QJSValue qjsvalue() const { return m_qjsvalue; }
 +
 +    int intProperty() const { return m_intProperty; }
 +    void setIntProperty(int i) { m_intProperty = i; emit intChanged(); }
 +    
 +signals:
 +    void basicSignal();
 +    void argumentSignal(int a, QString b, qreal c, MyEnum2 d, Qt::MouseButtons e);
++    void unnamedArgumentSignal(int a, qreal, QString c);
 +    void stringChanged();
 +    void urlChanged();
 +    void objectChanged();
 +    void anotherBasicSignal();
 +    void thirdBasicSignal();
 +    void signalWithUnknownType(const MyQmlObject::MyType &arg);
 +    void signalWithVariant(const QVariant &arg);
 +    void signalWithQJSValue(const QJSValue &arg);
++    void signalWithGlobalName(int parseInt);
 +    void intChanged();
 +
 +public slots:
 +    void deleteMe() { delete this; }
 +    void methodNoArgs() { m_methodCalled = true; }
 +    void method(int a) { if(a == 163) m_methodIntCalled = true; }
 +    void setString(const QString &s) { m_string = s; }
 +    void myinvokable(MyQmlObject *o) { myinvokableObject = o; }
 +    void variantMethod(const QVariant &v) { m_variant = v; }
 +    void qjsvalueMethod(const QJSValue &v) { m_qjsvalue = v; }
 +    void v8function(QQmlV8Function*);
 +
 +private:
 +    friend class tst_qqmlecmascript;
 +    bool m_methodCalled;
 +    bool m_methodIntCalled;
 +
 +    QObject *m_object;
 +    QString m_string;
 +    QUrl m_url;
 +    QList<QObject *> m_objectQList;
 +    int m_value;
 +    int m_resetProperty;
 +    QRegExp m_regExp;
 +    QVariant m_variant;
 +    QJSValue m_qjsvalue;
 +    int m_intProperty;
 +};
 +
 +QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES)
 +
 +class MyQmlContainer : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(QQmlListProperty<MyQmlObject> children READ children CONSTANT)
 +public:
 +    MyQmlContainer() {}
 +
 +    QQmlListProperty<MyQmlObject> children() { return QQmlListProperty<MyQmlObject>(this, m_children); }
 +
 +private:
 +    QList<MyQmlObject*> m_children;
 +};
 +
 +
 +class MyExpression : public QQmlExpression
 +{
 +    Q_OBJECT
 +public:
 +    MyExpression(QQmlContext *ctxt, const QString &expr)
 +        : QQmlExpression(ctxt, 0, expr), changed(false)
 +    {
 +        QObject::connect(this, SIGNAL(valueChanged()), this, SLOT(expressionValueChanged()));
 +        setNotifyOnValueChanged(true);
 +    }
 +
 +    bool changed;
 +
 +public slots:
 +    void expressionValueChanged() {
 +        changed = true;
 +    }
 +};
 +
 +
 +class MyDefaultObject1 : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int horseLegs READ horseLegs CONSTANT)
 +    Q_PROPERTY(int antLegs READ antLegs CONSTANT)
 +    Q_PROPERTY(int emuLegs READ emuLegs CONSTANT)
 +public:
 +    int horseLegs() const { return 4; }
 +    int antLegs() const { return 6; }
 +    int emuLegs() const { return 2; }
 +};
 +
 +class MyDefaultObject3 : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int antLegs READ antLegs CONSTANT)
 +    Q_PROPERTY(int humanLegs READ humanLegs CONSTANT)
 +public:
 +    int antLegs() const { return 7; } // Mutant
 +    int humanLegs() const { return 2; }
 +    int millipedeLegs() const { return 1000; }
 +};
 +
 +class MyDeferredObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
 +    Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty)
 +    Q_PROPERTY(QObject *objectProperty2 READ objectProperty2 WRITE setObjectProperty2)
 +    Q_CLASSINFO("DeferredPropertyNames", "value,objectProperty,objectProperty2")
 +
 +public:
 +    MyDeferredObject() : m_value(0), m_object(0), m_object2(0) {}
 +
 +    int value() const { return m_value; }
 +    void setValue(int v) { m_value = v; emit valueChanged(); }
 +
 +    QObject *objectProperty() const { return m_object; }
 +    void setObjectProperty(QObject *obj) { m_object = obj; }
 +
 +    QObject *objectProperty2() const { return m_object2; }
 +    void setObjectProperty2(QObject *obj) { m_object2 = obj; }
 +
 +signals:
 +    void valueChanged();
 +
 +private:
 +    int m_value;
 +    QObject *m_object;
 +    QObject *m_object2;
 +};
 +
 +class MyBaseExtendedObject : public QObject
 +{
 +Q_OBJECT
 +Q_PROPERTY(int baseProperty READ baseProperty WRITE setBaseProperty)
 +public:
 +    MyBaseExtendedObject() : m_value(0) {}
 +
 +    int baseProperty() const { return m_value; }
 +    void setBaseProperty(int v) { m_value = v; }
 +
 +private:
 +    int m_value;
 +};
 +
 +class MyExtendedObject : public MyBaseExtendedObject
 +{
 +Q_OBJECT
 +Q_PROPERTY(int coreProperty READ coreProperty WRITE setCoreProperty)
 +public:
 +    MyExtendedObject() : m_value(0) {}
 +
 +    int coreProperty() const { return m_value; }
 +    void setCoreProperty(int v) { m_value = v; }
 +
 +private:
 +    int m_value;
 +};
 +
 +class MyTypeObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_ENUMS(MyEnum)
 +    Q_FLAGS(MyFlags)
 +
 +    Q_PROPERTY(QString id READ id WRITE setId)
 +    Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty)
 +    Q_PROPERTY(QQmlComponent *componentProperty READ componentProperty WRITE setComponentProperty)
 +    Q_PROPERTY(MyFlags flagProperty READ flagProperty WRITE setFlagProperty)
 +    Q_PROPERTY(MyEnum enumProperty READ enumProperty WRITE setEnumProperty)
 +    Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty)
 +    Q_PROPERTY(uint uintProperty READ uintProperty WRITE setUintProperty)
 +    Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty)
 +    Q_PROPERTY(qreal realProperty READ realProperty WRITE setRealProperty)
 +    Q_PROPERTY(double doubleProperty READ doubleProperty WRITE setDoubleProperty)
 +    Q_PROPERTY(float floatProperty READ floatProperty WRITE setFloatProperty)
 +    Q_PROPERTY(QColor colorProperty READ colorProperty WRITE setColorProperty)
 +    Q_PROPERTY(QDate dateProperty READ dateProperty WRITE setDateProperty)
 +    Q_PROPERTY(QTime timeProperty READ timeProperty WRITE setTimeProperty)
 +    Q_PROPERTY(QDateTime dateTimeProperty READ dateTimeProperty WRITE setDateTimeProperty)
 +    Q_PROPERTY(QPoint pointProperty READ pointProperty WRITE setPointProperty)
 +    Q_PROPERTY(QPointF pointFProperty READ pointFProperty WRITE setPointFProperty)
 +    Q_PROPERTY(QSize sizeProperty READ sizeProperty WRITE setSizeProperty)
 +    Q_PROPERTY(QSizeF sizeFProperty READ sizeFProperty WRITE setSizeFProperty)
 +    Q_PROPERTY(QRect rectProperty READ rectProperty WRITE setRectProperty NOTIFY rectPropertyChanged)
 +    Q_PROPERTY(QRect rectProperty2 READ rectProperty2 WRITE setRectProperty2)
 +    Q_PROPERTY(QRectF rectFProperty READ rectFProperty WRITE setRectFProperty)
 +    Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty)
 +    Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty)
 +    Q_PROPERTY(QVector3D vectorProperty READ vectorProperty WRITE setVectorProperty)
 +    Q_PROPERTY(QUrl urlProperty READ urlProperty WRITE setUrlProperty)
 +
 +    Q_PROPERTY(QQmlScriptString scriptProperty READ scriptProperty WRITE setScriptProperty)
 +
 +public:
 +    MyTypeObject()
 +        : objectPropertyValue(0), componentPropertyValue(0) {}
 +
 +    QString idValue;
 +    QString id() const {
 +        return idValue;
 +    }
 +    void setId(const QString &v) {
 +        idValue = v;
 +    }
 +
 +    QObject *objectPropertyValue;
 +    QObject *objectProperty() const {
 +        return objectPropertyValue;
 +    }
 +    void setObjectProperty(QObject *v) {
 +        objectPropertyValue = v;
 +    }
 +
 +    QQmlComponent *componentPropertyValue;
 +    QQmlComponent *componentProperty() const {
 +        return componentPropertyValue;
 +    }
 +    void setComponentProperty(QQmlComponent *v) {
 +        componentPropertyValue = v;
 +    }
 +
 +    enum MyFlag { FlagVal1 = 0x01, FlagVal2 = 0x02, FlagVal3 = 0x04 };
 +    Q_DECLARE_FLAGS(MyFlags, MyFlag)
 +    MyFlags flagPropertyValue;
 +    MyFlags flagProperty() const {
 +        return flagPropertyValue;
 +    }
 +    void setFlagProperty(MyFlags v) {
 +        flagPropertyValue = v;
 +    }
 +
 +    enum MyEnum { EnumVal1, EnumVal2 };
 +    MyEnum enumPropertyValue;
 +    MyEnum enumProperty() const {
 +        return enumPropertyValue;
 +    }
 +    void setEnumProperty(MyEnum v) {
 +        enumPropertyValue = v;
 +    }
 +
 +    QString stringPropertyValue;
 +    QString stringProperty() const {
 +       return stringPropertyValue;
 +    }
 +    void setStringProperty(const QString &v) {
 +        stringPropertyValue = v;
 +    }
 +
 +    uint uintPropertyValue;
 +    uint uintProperty() const {
 +       return uintPropertyValue;
 +    }
 +    void setUintProperty(const uint &v) {
 +        uintPropertyValue = v;
 +    }
 +
 +    int intPropertyValue;
 +    int intProperty() const {
 +       return intPropertyValue;
 +    }
 +    void setIntProperty(const int &v) {
 +        intPropertyValue = v;
 +    }
 +
 +    qreal realPropertyValue;
 +    qreal realProperty() const {
 +       return realPropertyValue;
 +    }
 +    void setRealProperty(const qreal &v) {
 +        realPropertyValue = v;
 +    }
 +
 +    double doublePropertyValue;
 +    double doubleProperty() const {
 +       return doublePropertyValue;
 +    }
 +    void setDoubleProperty(const double &v) {
 +        doublePropertyValue = v;
 +    }
 +
 +    float floatPropertyValue;
 +    float floatProperty() const {
 +       return floatPropertyValue;
 +    }
 +    void setFloatProperty(const float &v) {
 +        floatPropertyValue = v;
 +    }
 +
 +    QColor colorPropertyValue;
 +    QColor colorProperty() const {
 +       return colorPropertyValue;
 +    }
 +    void setColorProperty(const QColor &v) {
 +        colorPropertyValue = v;
 +    }
 +
 +    QDate datePropertyValue;
 +    QDate dateProperty() const {
 +       return datePropertyValue;
 +    }
 +    void setDateProperty(const QDate &v) {
 +        datePropertyValue = v;
 +    }
 +
 +    QTime timePropertyValue;
 +    QTime timeProperty() const {
 +       return timePropertyValue;
 +    }
 +    void setTimeProperty(const QTime &v) {
 +        timePropertyValue = v;
 +    }
 +
 +    QDateTime dateTimePropertyValue;
 +    QDateTime dateTimeProperty() const {
 +       return dateTimePropertyValue;
 +    }
 +    void setDateTimeProperty(const QDateTime &v) {
 +        dateTimePropertyValue = v;
 +    }
 +
 +    QPoint pointPropertyValue;
 +    QPoint pointProperty() const {
 +       return pointPropertyValue;
 +    }
 +    void setPointProperty(const QPoint &v) {
 +        pointPropertyValue = v;
 +    }
 +
 +    QPointF pointFPropertyValue;
 +    QPointF pointFProperty() const {
 +       return pointFPropertyValue;
 +    }
 +    void setPointFProperty(const QPointF &v) {
 +        pointFPropertyValue = v;
 +    }
 +
 +    QSize sizePropertyValue;
 +    QSize sizeProperty() const {
 +       return sizePropertyValue;
 +    }
 +    void setSizeProperty(const QSize &v) {
 +        sizePropertyValue = v;
 +    }
 +
 +    QSizeF sizeFPropertyValue;
 +    QSizeF sizeFProperty() const {
 +       return sizeFPropertyValue;
 +    }
 +    void setSizeFProperty(const QSizeF &v) {
 +        sizeFPropertyValue = v;
 +    }
 +
 +    QRect rectPropertyValue;
 +    QRect rectProperty() const {
 +       return rectPropertyValue;
 +    }
 +    void setRectProperty(const QRect &v) {
 +        rectPropertyValue = v;
 +        emit rectPropertyChanged();
 +    }
 +
 +    QRect rectPropertyValue2;
 +    QRect rectProperty2() const {
 +       return rectPropertyValue2;
 +    }
 +    void setRectProperty2(const QRect &v) {
 +        rectPropertyValue2 = v;
 +    }
 +
 +    QRectF rectFPropertyValue;
 +    QRectF rectFProperty() const {
 +       return rectFPropertyValue;
 +    }
 +    void setRectFProperty(const QRectF &v) {
 +        rectFPropertyValue = v;
 +    }
 +
 +    bool boolPropertyValue;
 +    bool boolProperty() const {
 +       return boolPropertyValue;
 +    }
 +    void setBoolProperty(const bool &v) {
 +        boolPropertyValue = v;
 +    }
 +
 +    QVariant variantPropertyValue;
 +    QVariant variantProperty() const {
 +       return variantPropertyValue;
 +    }
 +    void setVariantProperty(const QVariant &v) {
 +        variantPropertyValue = v;
 +    }
 +
 +    QVector3D vectorPropertyValue;
 +    QVector3D vectorProperty() const {
 +        return vectorPropertyValue;
 +    }
 +    void setVectorProperty(const QVector3D &v) {
 +        vectorPropertyValue = v;
 +    }
 +
 +    QUrl urlPropertyValue;
 +    QUrl urlProperty() const {
 +        return urlPropertyValue;
 +    }
 +    void setUrlProperty(const QUrl &v) {
 +        urlPropertyValue = v;
 +    }
 +
 +    QQmlScriptString scriptPropertyValue;
 +    QQmlScriptString scriptProperty() const {
 +        return scriptPropertyValue;
 +    }
 +    void setScriptProperty(const QQmlScriptString &v) {
 +        scriptPropertyValue = v;
 +    }
 +
 +    void doAction() { emit action(); }
 +signals:
 +    void action();
 +    void rectPropertyChanged();
 +};
 +Q_DECLARE_OPERATORS_FOR_FLAGS(MyTypeObject::MyFlags)
 +
 +class MyDerivedObject : public MyTypeObject
 +{
 +    Q_OBJECT
 +public:
 +    Q_INVOKABLE bool intProperty() const {
 +        return true;
 +    }
 +};
 +
 +Q_DECLARE_METATYPE(QJSValue);
 +class MyInvokableBaseObject : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    inline ~MyInvokableBaseObject() = 0;
 +
 +    Q_INVOKABLE inline void method_inherited(int a);
 +    Q_INVOKABLE inline void method_overload();
 +};
 +
 +class MyInvokableObject : public MyInvokableBaseObject
 +{
 +    Q_OBJECT
 +    Q_ENUMS(TestEnum)
 +public:
 +    enum TestEnum { EnumValue1, EnumValue2 };
 +    MyInvokableObject() { reset(); }
 +
 +    int invoked() const { return m_invoked; }
 +    bool error() const { return m_invokedError; }
 +    const QVariantList &actuals() const { return m_actuals; }
 +    void reset() { m_invoked = -1; m_invokedError = false; m_actuals.clear(); }
 +
 +    Q_INVOKABLE QPointF method_get_QPointF() { return QPointF(99.3, -10.2); }
 +    Q_INVOKABLE QPoint method_get_QPoint() { return QPoint(9, 12); }
 +
 +    Q_INVOKABLE void method_NoArgs() { invoke(0); }
 +    Q_INVOKABLE int method_NoArgs_int() { invoke(1); return 6; }
 +    Q_INVOKABLE qreal method_NoArgs_real() { invoke(2); return 19.75; }
 +    Q_INVOKABLE QPointF method_NoArgs_QPointF() { invoke(3); return QPointF(123, 4.5); }
 +    Q_INVOKABLE QObject *method_NoArgs_QObject() { invoke(4); return this; }
 +    Q_INVOKABLE MyInvokableObject *method_NoArgs_unknown() { invoke(5); return this; }
 +    Q_INVOKABLE QJSValue method_NoArgs_QScriptValue() { invoke(6); return QJSValue("Hello world"); }
 +    Q_INVOKABLE QVariant method_NoArgs_QVariant() { invoke(7); return QVariant("QML rocks"); }
 +
 +    Q_INVOKABLE void method_int(int a) { invoke(8); m_actuals << a; }
 +    Q_INVOKABLE void method_intint(int a, int b) { invoke(9); m_actuals << a << b; }
 +    Q_INVOKABLE void method_real(qreal a) { invoke(10); m_actuals << a; }
 +    Q_INVOKABLE void method_QString(QString a) { invoke(11); m_actuals << a; }
 +    Q_INVOKABLE void method_QPointF(QPointF a) { invoke(12); m_actuals << a; }
 +    Q_INVOKABLE void method_QObject(QObject *a) { invoke(13); m_actuals << qVariantFromValue(a); }
 +    Q_INVOKABLE void method_QScriptValue(QJSValue a) { invoke(14); m_actuals << qVariantFromValue(a); }
 +    Q_INVOKABLE void method_intQScriptValue(int a, QJSValue b) { invoke(15); m_actuals << a << qVariantFromValue(b); }
 +    
 +    Q_INVOKABLE void method_overload(int a) { invoke(16); m_actuals << a; }
 +    Q_INVOKABLE void method_overload(int a, int b) { invoke(17); m_actuals << a << b; }
 +    Q_INVOKABLE void method_overload(QString a) { invoke(18); m_actuals << a; }
 +
 +    Q_INVOKABLE void method_with_enum(TestEnum e) { invoke(19); m_actuals << (int)e; }
 +
 +    Q_INVOKABLE int method_default(int a, int b = 19) { invoke(20); m_actuals << a << b; return b; }
 +
 +    Q_INVOKABLE void method_QVariant(QVariant a, QVariant b = QVariant()) { invoke(21); m_actuals << a << b; }
 +
 +private:
 +    friend class MyInvokableBaseObject;
 +    void invoke(int idx) { if (m_invoked != -1) m_invokedError = true; m_invoked = idx;}
 +    int m_invoked;
 +    bool m_invokedError;
 +    QVariantList m_actuals;
 +};
 +
 +MyInvokableBaseObject::~MyInvokableBaseObject() {}
 +
 +void MyInvokableBaseObject::method_inherited(int a)
 +{
 +    static_cast<MyInvokableObject *>(this)->invoke(-3);
 +    static_cast<MyInvokableObject *>(this)->m_actuals << a;
 +}
 +
 +// This is a hidden overload of the MyInvokableObject::method_overload() method
 +void MyInvokableBaseObject::method_overload()
 +{
 +    static_cast<MyInvokableObject *>(this)->invoke(-2);
 +}
 +
 +class NumberAssignment : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    Q_PROPERTY(qreal test1 READ test1 WRITE setTest1)
 +    qreal _test1;
 +    qreal test1() const { return _test1; }
 +    void setTest1(qreal v) { _test1 = v; }
 +
 +    Q_PROPERTY(qreal test2 READ test2 WRITE setTest2)
 +    qreal _test2;
 +    qreal test2() const { return _test2; }
 +    void setTest2(qreal v) { _test2 = v; }
 +
 +    Q_PROPERTY(qreal test3 READ test3 WRITE setTest3)
 +    qreal _test3;
 +    qreal test3() const { return _test3; }
 +    void setTest3(qreal v) { _test3 = v; }
 +
 +    Q_PROPERTY(qreal test4 READ test4 WRITE setTest4)
 +    qreal _test4;
 +    qreal test4() const { return _test4; }
 +    void setTest4(qreal v) { _test4 = v; }
 +
 +    Q_PROPERTY(int test5 READ test5 WRITE setTest5)
 +    int _test5;
 +    int test5() const { return _test5; }
 +    void setTest5(int v) { _test5 = v; }
 +
 +    Q_PROPERTY(int test6 READ test6 WRITE setTest6)
 +    int _test6;
 +    int test6() const { return _test6; }
 +    void setTest6(int v) { _test6 = v; }
 +
 +    Q_PROPERTY(int test7 READ test7 WRITE setTest7)
 +    int _test7;
 +    int test7() const { return _test7; }
 +    void setTest7(int v) { _test7 = v; }
 +
 +    Q_PROPERTY(int test8 READ test8 WRITE setTest8)
 +    int _test8;
 +    int test8() const { return _test8; }
 +    void setTest8(int v) { _test8 = v; }
 +
 +    Q_PROPERTY(unsigned int test9 READ test9 WRITE setTest9)
 +    unsigned int _test9;
 +    unsigned int test9() const { return _test9; }
 +    void setTest9(unsigned int v) { _test9 = v; }
 +
 +    Q_PROPERTY(unsigned int test10 READ test10 WRITE setTest10)
 +    unsigned int _test10;
 +    unsigned int test10() const { return _test10; }
 +    void setTest10(unsigned int v) { _test10 = v; }
 +
 +    Q_PROPERTY(unsigned int test11 READ test11 WRITE setTest11)
 +    unsigned int _test11;
 +    unsigned int test11() const { return _test11; }
 +    void setTest11(unsigned int v) { _test11 = v; }
 +
 +    Q_PROPERTY(unsigned int test12 READ test12 WRITE setTest12)
 +    unsigned int _test12;
 +    unsigned int test12() const { return _test12; }
 +    void setTest12(unsigned int v) { _test12 = v; }
 +};
 +
 +class DefaultPropertyExtendedObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(QObject *firstProperty READ firstProperty WRITE setFirstProperty)
 +    Q_PROPERTY(QObject *secondProperty READ secondProperty WRITE setSecondProperty)
 +public:
 +    DefaultPropertyExtendedObject(QObject *parent = 0) : QObject(parent), m_firstProperty(0), m_secondProperty(0) {}
 +
 +    QObject *firstProperty() const { return m_firstProperty; }
 +    QObject *secondProperty() const { return m_secondProperty; }
 +    void setFirstProperty(QObject *property) { m_firstProperty = property; }
 +    void setSecondProperty(QObject *property) { m_secondProperty = property; }
 +private:
 +    QObject* m_firstProperty;
 +    QObject* m_secondProperty;
 +};
 +
 +class OverrideDefaultPropertyObject : public DefaultPropertyExtendedObject
 +{
 +    Q_OBJECT
 +    Q_CLASSINFO("DefaultProperty", "secondProperty")
 +public:
 +    OverrideDefaultPropertyObject() {}
 +};
 +
 +class MyRevisionedBaseClassRegistered : public QObject
 +{
 +Q_OBJECT
 +    Q_PROPERTY(qreal propA READ propA WRITE setPropA NOTIFY propAChanged)
 +    Q_PROPERTY(qreal propB READ propB WRITE setPropB NOTIFY propBChanged REVISION 1)
 +
 +public:
 +    MyRevisionedBaseClassRegistered() : m_pa(1), m_pb(2) {}
 +
 +    qreal propA() const { return m_pa; }
 +    void setPropA(qreal p) {
 +        if (p != m_pa) {
 +            m_pa = p;
 +            emit propAChanged();
 +        }
 +    }
 +    qreal propB() const { return m_pb; }
 +    void setPropB(qreal p) {
 +        if (p != m_pb) {
 +            m_pb = p;
 +            emit propBChanged();
 +        }
 +    }
 +
 +    Q_INVOKABLE void methodA() { }
 +    Q_INVOKABLE Q_REVISION(1) void methodB() { }
 +
 +signals:
 +    void propAChanged();
 +    void propBChanged();
 +
 +    void signalA();
 +    Q_REVISION(1) void signalB();
 +
 +protected:
 +    qreal m_pa;
 +    qreal m_pb;
 +};
 +
 +class MyRevisionedBaseClassUnregistered : public MyRevisionedBaseClassRegistered
 +{
 +Q_OBJECT
 +    Q_PROPERTY(qreal propC READ propC WRITE setPropC NOTIFY propCChanged)
 +    Q_PROPERTY(qreal propD READ propD WRITE setPropD NOTIFY propDChanged REVISION 1)
 +
 +public:
 +    MyRevisionedBaseClassUnregistered() : m_pc(1), m_pd(2) {}
 +
 +    qreal propC() const { return m_pc; }
 +    void setPropC(qreal p) {
 +        if (p != m_pc) {
 +            m_pc = p;
 +            emit propCChanged();
 +        }
 +    }
 +    qreal propD() const { return m_pd; }
 +    void setPropD(qreal p) {
 +        if (p != m_pd) {
 +            m_pd = p;
 +            emit propDChanged();
 +        }
 +    }
 +
 +    Q_INVOKABLE void methodC() { }
 +    Q_INVOKABLE Q_REVISION(1) void methodD() { }
 +
 +signals:
 +    void propCChanged();
 +    void propDChanged();
 +
 +    void signalC();
 +    Q_REVISION(1) void signalD();
 +
 +protected:
 +    qreal m_pc;
 +    qreal m_pd;
 +};
 +
 +class MyRevisionedClass : public MyRevisionedBaseClassUnregistered
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(qreal prop1 READ prop1 WRITE setProp1 NOTIFY prop1Changed)
 +    Q_PROPERTY(qreal prop2 READ prop2 WRITE setProp2 NOTIFY prop2Changed REVISION 1)
 +
 +public:
 +    MyRevisionedClass() {}
 +
 +    qreal prop1() const { return m_p1; }
 +    void setProp1(qreal p) {
 +        if (p != m_p1) {
 +            m_p1 = p;
 +            emit prop1Changed();
 +        }
 +    }
 +    qreal prop2() const { return m_p2; }
 +    void setProp2(qreal p) {
 +        if (p != m_p2) {
 +            m_p2 = p;
 +            emit prop2Changed();
 +        }
 +    }
 +
 +    Q_INVOKABLE void method1() { }
 +    Q_INVOKABLE Q_REVISION(1) void method2() { }
 +
 +signals:
 +    void prop1Changed();
 +    void prop2Changed();
 +
 +    void signal1();
 +    Q_REVISION(1) void signal2();
 +
 +protected:
 +    qreal m_p1;
 +    qreal m_p2;
 +};
 +
 +class MyRevisionedSubclass : public MyRevisionedClass
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(qreal prop3 READ prop3 WRITE setProp3 NOTIFY prop3Changed)
 +    Q_PROPERTY(qreal prop4 READ prop4 WRITE setProp4 NOTIFY prop4Changed REVISION 1)
 +
 +public:
 +    MyRevisionedSubclass() : m_p3(3), m_p4(4) {}
 +
 +    qreal prop3() const { return m_p3; }
 +    void setProp3(qreal p) {
 +        if (p != m_p3) {
 +            m_p3 = p;
 +            emit prop3Changed();
 +        }
 +    }
 +    qreal prop4() const { return m_p4; }
 +    void setProp4(qreal p) {
 +        if (p != m_p4) {
 +            m_p4 = p;
 +            emit prop4Changed();
 +        }
 +    }
 +
 +    Q_INVOKABLE void method3() { }
 +    Q_INVOKABLE Q_REVISION(1) void method4() { }
 +
 +signals:
 +    void prop3Changed();
 +    void prop4Changed();
 +
 +    void signal3();
 +    Q_REVISION(1) void signal4();
 +
 +protected:
 +    qreal m_p3;
 +    qreal m_p4;
 +};
 +
 +QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered)
 +QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered)
 +QML_DECLARE_TYPE(MyRevisionedClass)
 +QML_DECLARE_TYPE(MyRevisionedSubclass)
 +Q_DECLARE_METATYPE(MyQmlObject::MyType)
 +
 +
 +class ScarceResourceObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(QPixmap scarceResource READ scarceResource WRITE setScarceResource NOTIFY scarceResourceChanged)
 +public:
 +    ScarceResourceObject(QObject *parent = 0) : QObject(parent), m_value(100, 100) { m_value.fill(Qt::blue); }
 +    ~ScarceResourceObject() {}
 +
 +    QPixmap scarceResource() const { return m_value; }
 +    void setScarceResource(QPixmap v) { m_value = v; emit scarceResourceChanged(); }
 +
 +    bool scarceResourceIsDetached() const { return m_value.isDetached(); }
 +
 +    // this particular one returns a new one each time
 +    // this means that every Scarce Resource Copy will
 +    // consume resources (so that we can track disposal
 +    // of v8 handles with circular references).
 +    Q_INVOKABLE QPixmap newScarceResource() const
 +    {
 +        QPixmap retn(800, 600);
 +        retn.fill(QColor(100, 110, 120, 45));
 +        return retn;
 +    }
 +
 +signals:
 +    void scarceResourceChanged();
 +
 +private:
 +    QPixmap m_value;
 +};
 +QML_DECLARE_TYPE(ScarceResourceObject)
 +
 +class testQObjectApi : public QObject
 +{
 +    Q_OBJECT
 +    Q_ENUMS(MyEnum)
 +    Q_PROPERTY (int qobjectTestProperty READ qobjectTestProperty NOTIFY qobjectTestPropertyChanged)
 +    Q_PROPERTY (int qobjectTestWritableProperty READ qobjectTestWritableProperty WRITE setQObjectTestWritableProperty NOTIFY qobjectTestWritablePropertyChanged)
 +
 +public:
 +    testQObjectApi(QObject* parent = 0)
 +        : QObject(parent), m_testProperty(0), m_testWritableProperty(0), m_methodCallCount(0)
 +    {
 +    }
 +
 +    ~testQObjectApi() {}
 +
 +    enum MyEnum { EnumValue1 = 25, EnumValue2 = 42 };
 +    Q_INVOKABLE int qobjectEnumTestMethod(MyEnum val) { return (static_cast<int>(val) + 5); }
 +    Q_INVOKABLE int qobjectTestMethod(int increment = 1) { m_methodCallCount += increment; return m_methodCallCount; }
 +
 +    int qobjectTestProperty() const { return m_testProperty; }
 +    void setQObjectTestProperty(int tp) { m_testProperty = tp; emit qobjectTestPropertyChanged(tp); }
 +
 +    int qobjectTestWritableProperty() const { return m_testWritableProperty; }
 +    void setQObjectTestWritableProperty(int tp) { m_testWritableProperty = tp; emit qobjectTestWritablePropertyChanged(tp); }
 +
 +signals:
 +    void qobjectTestPropertyChanged(int testProperty);
 +    void qobjectTestWritablePropertyChanged(int testWritableProperty);
 +
 +private:
 +    int m_testProperty;
 +    int m_testWritableProperty;
 +    int m_methodCallCount;
 +};
 +
 +class CircularReferenceObject : public QObject,
 +                                public QV8GCCallback::Node
 +{
 +    Q_OBJECT
 +
 +public:
 +    CircularReferenceObject(QObject *parent = 0)
 +        : QObject(parent), QV8GCCallback::Node(callback), m_referenced(0), m_dtorCount(0)
 +    {
 +        QV8GCCallback::addGcCallbackNode(this);
 +    }
 +
 +    ~CircularReferenceObject()
 +    {
 +        if (m_dtorCount) *m_dtorCount = *m_dtorCount + 1;
 +    }
 +
 +    Q_INVOKABLE void setDtorCount(int *dtorCount)
 +    {
 +        m_dtorCount = dtorCount;
 +    }
 +
 +    Q_INVOKABLE CircularReferenceObject *generate(QObject *parent = 0)
 +    {
 +        CircularReferenceObject *retn = new CircularReferenceObject(parent);
 +        retn->m_dtorCount = m_dtorCount;
 +        retn->m_engine = m_engine;
 +        return retn;
 +    }
 +
 +    Q_INVOKABLE void addReference(QObject *other)
 +    {
 +        m_referenced = other;
 +    }
 +
 +    static void callback(QV8GCCallback::Node *n)
 +    {
 +        CircularReferenceObject *cro = static_cast<CircularReferenceObject*>(n);
 +        if (cro->m_referenced) {
 +            cro->m_engine->addRelationshipForGC(cro, cro->m_referenced);
 +        }
 +    }
 +
 +    void setEngine(QQmlEngine* declarativeEngine)
 +    {
 +        m_engine = QQmlEnginePrivate::get(declarativeEngine)->v8engine();
 +    }
 +
 +private:
 +    QObject *m_referenced;
 +    int *m_dtorCount;
 +    QV8Engine* m_engine;
 +};
 +Q_DECLARE_METATYPE(CircularReferenceObject*)
 +
 +class CircularReferenceHandle : public QObject,
 +                                public QV8GCCallback::Node
 +{
 +    Q_OBJECT
 +
 +public:
 +    CircularReferenceHandle(QObject *parent = 0)
 +        : QObject(parent), QV8GCCallback::Node(gccallback), m_dtorCount(0), m_engine(0)
 +    {
 +        QV8GCCallback::addGcCallbackNode(this);
 +    }
 +
 +    ~CircularReferenceHandle()
 +    {
 +        if (m_dtorCount) *m_dtorCount = *m_dtorCount + 1;
 +    }
 +
 +    Q_INVOKABLE void setDtorCount(int *dtorCount)
 +    {
 +        m_dtorCount = dtorCount;
 +    }
 +
 +    Q_INVOKABLE CircularReferenceHandle *generate(QObject *parent = 0)
 +    {
 +        CircularReferenceHandle *retn = new CircularReferenceHandle(parent);
 +        retn->m_dtorCount = m_dtorCount;
 +        retn->m_engine = m_engine;
 +        return retn;
 +    }
 +
 +    Q_INVOKABLE void addReference(v8::Persistent<v8::Value> handle)
 +    {
 +        m_referenced = qPersistentNew(handle);
 +        m_referenced.MakeWeak(static_cast<void*>(this), wrcallback);
 +    }
 +
 +    static void wrcallback(v8::Persistent<v8::Value> handle, void *params)
 +    {
 +        CircularReferenceHandle *crh = static_cast<CircularReferenceHandle*>(params);
 +        qPersistentDispose(handle);
 +        crh->m_referenced.Clear();
 +    }
 +
 +    static void gccallback(QV8GCCallback::Node *n)
 +    {
 +        CircularReferenceHandle *crh = static_cast<CircularReferenceHandle*>(n);
 +        crh->m_engine->addRelationshipForGC(crh, crh->m_referenced);
 +    }
 +
 +    void setEngine(QQmlEngine* declarativeEngine)
 +    {
 +        m_engine = QQmlEnginePrivate::get(declarativeEngine)->v8engine();
 +    }
 +
 +private:
 +    v8::Persistent<v8::Value> m_referenced;
 +    int *m_dtorCount;
 +    QV8Engine* m_engine;
 +};
 +Q_DECLARE_METATYPE(CircularReferenceHandle*)
 +
 +class MyDynamicCreationDestructionObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY (int intProperty READ intProperty WRITE setIntProperty NOTIFY intPropertyChanged)
 +
 +public:
 +    MyDynamicCreationDestructionObject(QObject *parent = 0) : QObject(parent), m_intProperty(0), m_dtorCount(0)
 +    {
 +    }
 +
 +    ~MyDynamicCreationDestructionObject()
 +    {
 +        if (m_dtorCount) {
 +            (*m_dtorCount)++;
 +        }
 +    }
 +
 +    int intProperty() const { return m_intProperty; }
 +    void setIntProperty(int val) { m_intProperty = val; emit intPropertyChanged(); }
 +
 +    Q_INVOKABLE MyDynamicCreationDestructionObject *createNew()
 +    {
 +        // no parent == ownership transfers to JS; same dtor counter.
 +        MyDynamicCreationDestructionObject *retn = new MyDynamicCreationDestructionObject;
 +        retn->setDtorCount(m_dtorCount);
 +        return retn;
 +    }
 +
 +    void setDtorCount(int *dtorCount)
 +    {
 +        m_dtorCount = dtorCount;
 +    }
 +
 +signals:
 +    void intPropertyChanged();
 +
 +private:
 +    int m_intProperty;
 +    int *m_dtorCount;
 +};
 +
 +class WriteCounter : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value WRITE setValue);
 +public:
 +    WriteCounter() : m_value(0), m_count(0) {}
 +
 +    int value() const { return m_value; }
 +    void setValue(int v) { m_value = v; ++m_count; }
 +
 +    int count() const { return m_count; }
 +
 +private:
 +    int m_value;
 +    int m_count;
 +};
 +
 +class MySequenceConversionObject : public QObject
 +{
 +    Q_OBJECT
 +
 +    Q_PROPERTY (QList<int> intListProperty READ intListProperty WRITE setIntListProperty NOTIFY intListPropertyChanged)
 +    Q_PROPERTY (QList<int> intListProperty2 READ intListProperty2 WRITE setIntListProperty2 NOTIFY intListProperty2Changed)
 +    Q_PROPERTY (QList<qreal> qrealListProperty READ qrealListProperty WRITE setQrealListProperty NOTIFY qrealListPropertyChanged)
 +    Q_PROPERTY (QList<bool> boolListProperty READ boolListProperty WRITE setBoolListProperty NOTIFY boolListPropertyChanged)
 +    Q_PROPERTY (QList<QString> stringListProperty READ stringListProperty WRITE setStringListProperty NOTIFY stringListPropertyChanged)
 +    Q_PROPERTY (QList<QUrl> urlListProperty READ urlListProperty WRITE setUrlListProperty NOTIFY urlListPropertyChanged)
 +    Q_PROPERTY (QStringList qstringListProperty READ qstringListProperty WRITE setQStringListProperty NOTIFY qstringListPropertyChanged)
 +
 +    Q_PROPERTY (QList<QPoint> pointListProperty READ pointListProperty WRITE setPointListProperty NOTIFY pointListPropertyChanged)
 +    Q_PROPERTY (QList<QVariant> variantListProperty READ variantListProperty WRITE setVariantListProperty NOTIFY variantListPropertyChanged)
 +
 +    Q_PROPERTY (qint32 maxIndex READ maxIndex CONSTANT)
 +    Q_PROPERTY (quint32 tooBigIndex READ tooBigIndex CONSTANT)
 +    Q_PROPERTY (qint32 negativeIndex READ negativeIndex CONSTANT)
 +
 +public:
 +    MySequenceConversionObject()
 +    {
 +        m_intList << 1 << 2 << 3 << 4;
 +        m_intList2 << 1 << 2 << 3 << 4;
 +        m_qrealList << 1.1 << 2.2 << 3.3 << 4.4;
 +        m_boolList << true << false << true << false;
 +        m_stringList << QLatin1String("first") << QLatin1String("second") << QLatin1String("third") << QLatin1String("fourth");
 +        m_urlList << QUrl("http://www.example1.com") << QUrl("http://www.example2.com") << QUrl("http://www.example3.com");
 +        m_qstringList << QLatin1String("first") << QLatin1String("second") << QLatin1String("third") << QLatin1String("fourth");
 +
 +        m_pointList << QPoint(1, 2) << QPoint(3, 4) << QPoint(5, 6);
 +        m_variantList << QVariant(QLatin1String("one")) << QVariant(true) << QVariant(3);
 +    }
 +
 +    ~MySequenceConversionObject() {}
 +
 +    qint32 maxIndex() const
 +    {
 +        return INT_MAX;
 +    }
 +    quint32 tooBigIndex() const
 +    {
 +        quint32 retn = 7;
 +        retn += INT_MAX;
 +        return retn;
 +    }
 +    qint32 negativeIndex() const
 +    {
 +        return -5;
 +    }
 +
 +    QList<int> intListProperty() const { return m_intList; }
 +    void setIntListProperty(const QList<int> &list) { m_intList = list; emit intListPropertyChanged(); }
 +    QList<int> intListProperty2() const { return m_intList2; }
 +    void setIntListProperty2(const QList<int> &list) { m_intList2 = list; emit intListProperty2Changed(); }
 +    QList<qreal> qrealListProperty() const { return m_qrealList; }
 +    void setQrealListProperty(const QList<qreal> &list) { m_qrealList = list; emit qrealListPropertyChanged(); }
 +    QList<bool> boolListProperty() const { return m_boolList; }
 +    void setBoolListProperty(const QList<bool> &list) { m_boolList = list; emit boolListPropertyChanged(); }
 +    QList<QString> stringListProperty() const { return m_stringList; }
 +    void setStringListProperty(const QList<QString> &list) { m_stringList = list; emit stringListPropertyChanged(); }
 +    QList<QUrl> urlListProperty() const { return m_urlList; }
 +    void setUrlListProperty(const QList<QUrl> &list) { m_urlList = list; emit urlListPropertyChanged(); }
 +    QStringList qstringListProperty() const { return m_qstringList; }
 +    void setQStringListProperty(const QStringList &list) { m_qstringList = list; emit qstringListPropertyChanged(); }
 +    QList<QPoint> pointListProperty() const { return m_pointList; }
 +    void setPointListProperty(const QList<QPoint> &list) { m_pointList = list; emit pointListPropertyChanged(); }
 +    QList<QVariant> variantListProperty() const { return m_variantList; }
 +    void setVariantListProperty(const QList<QVariant> &list) { m_variantList = list; emit variantListPropertyChanged(); }
 +
 +    // now for "copy resource" sequences:
 +    Q_INVOKABLE QList<int> generateIntSequence() const { QList<int> retn; retn << 1 << 2 << 3; return retn; }
 +    Q_INVOKABLE QList<qreal> generateQrealSequence() const { QList<qreal> retn; retn << 1.1 << 2.2 << 3.3; return retn; }
 +    Q_INVOKABLE QList<bool> generateBoolSequence() const { QList<bool> retn; retn << true << false << true; return retn; }
 +    Q_INVOKABLE QList<QString> generateStringSequence() const { QList<QString> retn; retn << "one" << "two" << "three"; return retn; }
 +    Q_INVOKABLE QList<QUrl> generateUrlSequence() const { QList<QUrl> retn; retn << QUrl("http://www.example1.com") << QUrl("http://www.example2.com") << QUrl("http://www.example3.com"); return retn; }
 +    Q_INVOKABLE QStringList generateQStringSequence() const { QStringList retn; retn << "one" << "two" << "three"; return retn; }
 +
 +    // "reference resource" underlying qobject deletion test:
 +    Q_INVOKABLE MySequenceConversionObject *generateTestObject() const { return new MySequenceConversionObject; }
 +    Q_INVOKABLE void deleteTestObject(QObject *object) const { delete object; }
 +
 +signals:
 +    void intListPropertyChanged();
 +    void intListProperty2Changed();
 +    void qrealListPropertyChanged();
 +    void boolListPropertyChanged();
 +    void stringListPropertyChanged();
 +    void urlListPropertyChanged();
 +    void qstringListPropertyChanged();
 +    void pointListPropertyChanged();
 +    void variantListPropertyChanged();
 +
 +private:
 +    QList<int> m_intList;
 +    QList<int> m_intList2;
 +    QList<qreal> m_qrealList;
 +    QList<bool> m_boolList;
 +    QList<QString> m_stringList;
 +    QList<QUrl> m_urlList;
 +    QStringList m_qstringList;
 +
 +    QList<QPoint> m_pointList; // not a supported sequence type
 +    QList<QVariant> m_variantList; // not a supported sequence type, but QVariantList support is hardcoded.
 +};
 +
 +class MyDeleteObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(QObject *nestedObject READ nestedObject NOTIFY nestedObjectChanged);
 +    Q_PROPERTY(int deleteNestedObject READ deleteNestedObject NOTIFY deleteNestedObjectChanged);
 +
 +public:
 +    MyDeleteObject() : m_nestedObject(new MyQmlObject) {}
 +
 +    QObject *nestedObject() const { return m_nestedObject; }
 +    int deleteNestedObject() { delete m_nestedObject; m_nestedObject = 0; return 1; }
 +
 +signals:
 +    void nestedObjectChanged();
 +    void deleteNestedObjectChanged();
 +
 +private:
 +    MyQmlObject *m_nestedObject;
 +};
 +
 +void registerTypes();
 +
 +#endif // TESTTYPES_H
 +
index af219c8,0000000..676557a
mode 100644,000000..100644
--- /dev/null
@@@ -1,6062 -1,0 +1,6097 @@@
-     QString warning = component.url().toString() + ":16: SyntaxError: Unexpected token ILLEGAL";
-     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <QtTest/QtTest>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlexpression.h>
 +#include <QtQml/qqmlcontext.h>
 +#include <QtCore/qfileinfo.h>
 +#include <QtCore/qdebug.h>
 +#include <QtQml/private/qqmlguard_p.h>
 +#include <QtCore/qdir.h>
 +#include <QtCore/qnumeric.h>
 +#include <private/qqmlengine_p.h>
 +#include <private/qqmlvmemetaobject_p.h>
 +#include <private/qv4compiler_p.h>
 +#include "testtypes.h"
 +#include "testhttpserver.h"
 +#include "../../shared/util.h"
 +
 +/*
 +This test covers evaluation of ECMAScript expressions and bindings from within
 +QML.  This does not include static QML language issues.
 +
 +Static QML language issues are covered in qmllanguage
 +*/
 +
 +class tst_qqmlecmascript : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_qqmlecmascript() {}
 +
 +private slots:
 +    void initTestCase();
 +    void assignBasicTypes();
 +    void idShortcutInvalidates();
 +    void boolPropertiesEvaluateAsBool();
 +    void methods();
 +    void signalAssignment();
 +    void bindingLoop();
 +    void basicExpressions();
 +    void basicExpressions_data();
 +    void arrayExpressions();
 +    void contextPropertiesTriggerReeval();
 +    void objectPropertiesTriggerReeval();
 +    void deferredProperties();
 +    void deferredPropertiesErrors();
 +    void extensionObjects();
 +    void overrideExtensionProperties();
 +    void attachedProperties();
 +    void enums();
 +    void valueTypeFunctions();
 +    void constantsOverrideBindings();
 +    void outerBindingOverridesInnerBinding();
 +    void aliasPropertyAndBinding();
 +    void aliasPropertyReset();
 +    void nonExistentAttachedObject();
 +    void scope();
 +    void importScope();
 +    void signalParameterTypes();
 +    void objectsCompareAsEqual();
 +    void dynamicCreation_data();
 +    void dynamicCreation();
 +    void dynamicDestruction();
 +    void objectToString();
 +    void objectHasOwnProperty();
 +    void selfDeletingBinding();
 +    void extendedObjectPropertyLookup();
 +    void extendedObjectPropertyLookup2();
 +    void scriptErrors();
 +    void functionErrors();
 +    void propertyAssignmentErrors();
 +    void signalTriggeredBindings();
 +    void listProperties();
 +    void exceptionClearsOnReeval();
 +    void exceptionSlotProducesWarning();
 +    void exceptionBindingProducesWarning();
 +    void compileInvalidBinding();
 +    void transientErrors();
 +    void shutdownErrors();
 +    void compositePropertyType();
 +    void jsObject();
 +    void undefinedResetsProperty();
 +    void listToVariant();
 +    void listAssignment();
 +    void multiEngineObject();
 +    void deletedObject();
 +    void attachedPropertyScope();
 +    void scriptConnect();
 +    void scriptDisconnect();
 +    void ownership();
 +    void cppOwnershipReturnValue();
 +    void ownershipCustomReturnValue();
 +    void qlistqobjectMethods();
 +    void strictlyEquals();
 +    void compiled();
 +    void numberAssignment();
 +    void propertySplicing();
 +    void signalWithUnknownTypes();
 +    void signalWithJSValueInVariant_data();
 +    void signalWithJSValueInVariant();
 +    void signalWithJSValueInVariant_twoEngines_data();
 +    void signalWithJSValueInVariant_twoEngines();
 +    void signalWithQJSValue_data();
 +    void signalWithQJSValue();
 +    void moduleApi_data();
 +    void moduleApi();
 +    void importScripts_data();
 +    void importScripts();
 +    void scarceResources();
 +    void scarceResources_data();
 +    void scarceResources_other();
 +    void propertyChangeSlots();
 +    void propertyVar_data();
 +    void propertyVar();
 +    void propertyVarCpp();
 +    void propertyVarOwnership();
 +    void propertyVarImplicitOwnership();
 +    void propertyVarReparent();
 +    void propertyVarReparentNullContext();
 +    void propertyVarCircular();
 +    void propertyVarCircular2();
 +    void propertyVarInheritance();
 +    void propertyVarInheritance2();
 +    void elementAssign();
 +    void objectPassThroughSignals();
 +    void objectConversion();
 +    void booleanConversion();
 +    void handleReferenceManagement();
 +    void stringArg();
 +    void readonlyDeclaration();
 +    void sequenceConversionRead();
 +    void sequenceConversionWrite();
 +    void sequenceConversionArray();
 +    void sequenceConversionIndexes();
 +    void sequenceConversionThreads();
 +    void sequenceConversionBindings();
 +    void sequenceConversionCopy();
 +    void assignSequenceTypes();
 +    void qtbug_22464();
 +    void qtbug_21580();
 +
 +    void bug1();
 +    void bug2();
 +    void dynamicCreationCrash();
 +    void dynamicCreationOwnership();
 +    void regExpBug();
 +    void nullObjectBinding();
 +    void deletedEngine();
 +    void libraryScriptAssert();
 +    void variantsAssignedUndefined();
 +    void qtbug_9792();
 +    void qtcreatorbug_1289();
 +    void noSpuriousWarningsAtShutdown();
 +    void canAssignNullToQObject();
 +    void functionAssignment_fromBinding();
 +    void functionAssignment_fromJS();
 +    void functionAssignment_fromJS_data();
 +    void functionAssignmentfromJS_invalid();
 +    void eval();
 +    void function();
 +    void functionException();
 +    void qtbug_10696();
 +    void qtbug_11606();
 +    void qtbug_11600();
 +    void qtbug_21864();
 +    void qobjectConnectionListExceptionHandling();
 +    void nonscriptable();
 +    void deleteLater();
 +    void in();
 +    void typeOf();
 +    void sharedAttachedObject();
 +    void objectName();
 +    void writeRemovesBinding();
 +    void aliasBindingsAssignCorrectly();
 +    void aliasBindingsOverrideTarget();
 +    void aliasWritesOverrideBindings();
 +    void aliasToCompositeElement();
 +    void realToInt();
 +    void urlProperty();
 +    void urlPropertyWithEncoding();
 +    void urlListPropertyWithEncoding();
 +    void dynamicString();
 +    void include();
 +    void signalHandlers();
 +    void doubleEvaluate();
 +    void forInLoop();
 +    void nonNotifyable();
 +    void deleteWhileBindingRunning();
 +    void callQtInvokables();
 +    void invokableObjectArg();
 +    void invokableObjectRet();
 +    void qtbug_20344();
 +    void qtbug_22679();
 +    void qtbug_22843_data();
 +    void qtbug_22843();
 +    void rewriteMultiLineStrings();
 +    void revisionErrors();
 +    void revision();
 +    void invokableWithQObjectDerived();
 +
 +    void automaticSemicolon();
 +    void unaryExpression();
 +    void switchStatement();
 +    void withStatement();
 +    void tryStatement();
 +
 +private:
 +    static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
 +    QQmlEngine engine;
 +};
 +
 +void tst_qqmlecmascript::initTestCase()
 +{
 +    QQmlDataTest::initTestCase();
 +    registerTypes();
 +}
 +
 +void tst_qqmlecmascript::assignBasicTypes()
 +{
 +    {
 +    QQmlComponent component(&engine, testFileUrl("assignBasicTypes.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
 +    QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
 +    QCOMPARE(object->stringProperty(), QString("Hello World!"));
 +    QCOMPARE(object->uintProperty(), uint(10));
 +    QCOMPARE(object->intProperty(), -19);
 +    QCOMPARE((float)object->realProperty(), float(23.2));
 +    QCOMPARE((float)object->doubleProperty(), float(-19.75));
 +    QCOMPARE((float)object->floatProperty(), float(8.5));
 +    QCOMPARE(object->colorProperty(), QColor("red"));
 +    QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
 +    QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
 +    QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
 +    QCOMPARE(object->pointProperty(), QPoint(99,13));
 +    QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
 +    QCOMPARE(object->sizeProperty(), QSize(99, 13));
 +    QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
 +    QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
 +    QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
 +    QCOMPARE(object->boolProperty(), true);
 +    QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
 +    QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
 +    QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
 +    delete object;
 +    }
 +    {
 +    QQmlComponent component(&engine, testFileUrl("assignBasicTypes.2.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
 +    QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
 +    QCOMPARE(object->stringProperty(), QString("Hello World!"));
 +    QCOMPARE(object->uintProperty(), uint(10));
 +    QCOMPARE(object->intProperty(), -19);
 +    QCOMPARE((float)object->realProperty(), float(23.2));
 +    QCOMPARE((float)object->doubleProperty(), float(-19.75));
 +    QCOMPARE((float)object->floatProperty(), float(8.5));
 +    QCOMPARE(object->colorProperty(), QColor("red"));
 +    QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
 +    QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
 +    QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
 +    QCOMPARE(object->pointProperty(), QPoint(99,13));
 +    QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
 +    QCOMPARE(object->sizeProperty(), QSize(99, 13));
 +    QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
 +    QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
 +    QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
 +    QCOMPARE(object->boolProperty(), true);
 +    QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
 +    QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
 +    QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
 +    delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::idShortcutInvalidates()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("idShortcutInvalidates.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +        QVERIFY(object->objectProperty() != 0);
 +        delete object->objectProperty();
 +        QVERIFY(object->objectProperty() == 0);
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("idShortcutInvalidates.1.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +        QVERIFY(object->objectProperty() != 0);
 +        delete object->objectProperty();
 +        QVERIFY(object->objectProperty() == 0);
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::boolPropertiesEvaluateAsBool()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("boolPropertiesEvaluateAsBool.1.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->stringProperty(), QLatin1String("pass"));
 +        delete object;
 +    }
 +    {
 +        QQmlComponent component(&engine, testFileUrl("boolPropertiesEvaluateAsBool.2.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->stringProperty(), QLatin1String("pass"));
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::signalAssignment()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("signalAssignment.1.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->string(), QString());
 +        emit object->basicSignal();
 +        QCOMPARE(object->string(), QString("pass"));
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("signalAssignment.2.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->string(), QString());
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
 +        delete object;
 +    }
++
++    {
++        QQmlComponent component(&engine, testFileUrl("signalAssignment.3.qml"));
++        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
++        QVERIFY(object != 0);
++        QCOMPARE(object->string(), QString());
++        emit object->unnamedArgumentSignal(19, 10.25, "Hello world!");
++        QEXPECT_FAIL("", "QTBUG-24481", Continue);
++        QCOMPARE(object->string(), QString("pass 19 Hello world!"));
++        delete object;
++    }
++
++    {
++        QQmlComponent component(&engine, testFileUrl("signalAssignment.4.qml"));
++        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
++        QVERIFY(object != 0);
++        QCOMPARE(object->string(), QString());
++        emit object->signalWithGlobalName(19);
++        QCOMPARE(object->string(), QString("pass 5"));
++        delete object;
++    }
 +}
 +
 +void tst_qqmlecmascript::methods()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("methods.1.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->methodCalled(), false);
 +        QCOMPARE(object->methodIntCalled(), false);
 +        emit object->basicSignal();
 +        QCOMPARE(object->methodCalled(), true);
 +        QCOMPARE(object->methodIntCalled(), false);
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("methods.2.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->methodCalled(), false);
 +        QCOMPARE(object->methodIntCalled(), false);
 +        emit object->basicSignal();
 +        QCOMPARE(object->methodCalled(), false);
 +        QCOMPARE(object->methodIntCalled(), true);
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("methods.3.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->property("test").toInt(), 19);
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("methods.4.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->property("test").toInt(), 19);
 +        QCOMPARE(object->property("test2").toInt(), 17);
 +        QCOMPARE(object->property("test3").toInt(), 16);
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("methods.5.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->property("test").toInt(), 9);
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::bindingLoop()
 +{
 +    QQmlComponent component(&engine, testFileUrl("bindingLoop.qml"));
 +    QString warning = component.url().toString() + ":5:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::basicExpressions_data()
 +{
 +    QTest::addColumn<QString>("expression");
 +    QTest::addColumn<QVariant>("result");
 +    QTest::addColumn<bool>("nest");
 +
 +    QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
 +    QTest::newRow("Context property") << "a" << QVariant(1944) << false;
 +    QTest::newRow("Context property") << "a" << QVariant(1944) << true;
 +    QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
 +    QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
 +    QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
 +    QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
 +    QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
 +    QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
 +    QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
 +    QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
 +    QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
 +    QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
 +    QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
 +    QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
 +    QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
 +    QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
 +    QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
 +    QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
 +}
 +
 +void tst_qqmlecmascript::basicExpressions()
 +{
 +    QFETCH(QString, expression);
 +    QFETCH(QVariant, result);
 +    QFETCH(bool, nest);
 +
 +    MyQmlObject object1;
 +    MyQmlObject object2;
 +    MyQmlObject object3;
 +    MyDefaultObject1 default1;
 +    MyDefaultObject3 default3;
 +    object1.setStringProperty("Object1");
 +    object2.setStringProperty("Object2");
 +    object3.setStringProperty("Object3");
 +
 +    QQmlContext context(engine.rootContext());
 +    QQmlContext nestedContext(&context);
 +
 +    context.setContextObject(&default1);
 +    context.setContextProperty("a", QVariant(1944));
 +    context.setContextProperty("b", QVariant("Milk"));
 +    context.setContextProperty("object", &object1);
 +    context.setContextProperty("objectOverride", &object2);
 +    nestedContext.setContextObject(&default3);
 +    nestedContext.setContextProperty("b", QVariant("Cow"));
 +    nestedContext.setContextProperty("objectOverride", &object3);
 +    nestedContext.setContextProperty("millipedeLegs", QVariant(100));
 +
 +    MyExpression expr(nest?&nestedContext:&context, expression);
 +    QCOMPARE(expr.evaluate(), result);
 +}
 +
 +void tst_qqmlecmascript::arrayExpressions()
 +{
 +    QObject obj1;
 +    QObject obj2;
 +    QObject obj3;
 +
 +    QQmlContext context(engine.rootContext());
 +    context.setContextProperty("a", &obj1);
 +    context.setContextProperty("b", &obj2);
 +    context.setContextProperty("c", &obj3);
 +
 +    MyExpression expr(&context, "[a, b, c, 10]");
 +    QVariant result = expr.evaluate();
 +    QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
 +    QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
 +    QCOMPARE(list.count(), 4);
 +    QCOMPARE(list.at(0), &obj1);
 +    QCOMPARE(list.at(1), &obj2);
 +    QCOMPARE(list.at(2), &obj3);
 +    QCOMPARE(list.at(3), (QObject *)0);
 +}
 +
 +// Tests that modifying a context property will reevaluate expressions
 +void tst_qqmlecmascript::contextPropertiesTriggerReeval()
 +{
 +    QQmlContext context(engine.rootContext());
 +    MyQmlObject object1;
 +    MyQmlObject object2;
 +    MyQmlObject *object3 = new MyQmlObject;
 +
 +    object1.setStringProperty("Hello");
 +    object2.setStringProperty("World");
 +
 +    context.setContextProperty("testProp", QVariant(1));
 +    context.setContextProperty("testObj", &object1);
 +    context.setContextProperty("testObj2", object3);
 +
 +    { 
 +        MyExpression expr(&context, "testProp + 1");
 +        QCOMPARE(expr.changed, false);
 +        QCOMPARE(expr.evaluate(), QVariant(2));
 +
 +        context.setContextProperty("testProp", QVariant(2));
 +        QCOMPARE(expr.changed, true);
 +        QCOMPARE(expr.evaluate(), QVariant(3));
 +    }
 +
 +    { 
 +        MyExpression expr(&context, "testProp + testProp + testProp");
 +        QCOMPARE(expr.changed, false);
 +        QCOMPARE(expr.evaluate(), QVariant(6));
 +
 +        context.setContextProperty("testProp", QVariant(4));
 +        QCOMPARE(expr.changed, true);
 +        QCOMPARE(expr.evaluate(), QVariant(12));
 +    }
 +
 +    { 
 +        MyExpression expr(&context, "testObj.stringProperty");
 +        QCOMPARE(expr.changed, false);
 +        QCOMPARE(expr.evaluate(), QVariant("Hello"));
 +
 +        context.setContextProperty("testObj", &object2);
 +        QCOMPARE(expr.changed, true);
 +        QCOMPARE(expr.evaluate(), QVariant("World"));
 +    }
 +
 +    { 
 +        MyExpression expr(&context, "testObj.stringProperty /**/");
 +        QCOMPARE(expr.changed, false);
 +        QCOMPARE(expr.evaluate(), QVariant("World"));
 +
 +        context.setContextProperty("testObj", &object1);
 +        QCOMPARE(expr.changed, true);
 +        QCOMPARE(expr.evaluate(), QVariant("Hello"));
 +    }
 +
 +    { 
 +        MyExpression expr(&context, "testObj2");
 +        QCOMPARE(expr.changed, false);
 +        QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
 +    }
 +
 +    delete object3;
 +}
 +
 +void tst_qqmlecmascript::objectPropertiesTriggerReeval()
 +{
 +    QQmlContext context(engine.rootContext());
 +    MyQmlObject object1;
 +    MyQmlObject object2;
 +    MyQmlObject object3;
 +    context.setContextProperty("testObj", &object1);
 +
 +    object1.setStringProperty(QLatin1String("Hello"));
 +    object2.setStringProperty(QLatin1String("Dog"));
 +    object3.setStringProperty(QLatin1String("Cat"));
 +
 +    { 
 +        MyExpression expr(&context, "testObj.stringProperty");
 +        QCOMPARE(expr.changed, false);
 +        QCOMPARE(expr.evaluate(), QVariant("Hello"));
 +
 +        object1.setStringProperty(QLatin1String("World"));
 +        QCOMPARE(expr.changed, true);
 +        QCOMPARE(expr.evaluate(), QVariant("World"));
 +    }
 +
 +    { 
 +        MyExpression expr(&context, "testObj.objectProperty.stringProperty");
 +        QCOMPARE(expr.changed, false);
 +        QCOMPARE(expr.evaluate(), QVariant());
 +
 +        object1.setObjectProperty(&object2);
 +        QCOMPARE(expr.changed, true);
 +        expr.changed = false;
 +        QCOMPARE(expr.evaluate(), QVariant("Dog"));
 +
 +        object1.setObjectProperty(&object3);
 +        QCOMPARE(expr.changed, true);
 +        expr.changed = false;
 +        QCOMPARE(expr.evaluate(), QVariant("Cat"));
 +
 +        object1.setObjectProperty(0);
 +        QCOMPARE(expr.changed, true);
 +        expr.changed = false;
 +        QCOMPARE(expr.evaluate(), QVariant());
 +
 +        object1.setObjectProperty(&object3);
 +        QCOMPARE(expr.changed, true);
 +        expr.changed = false;
 +        QCOMPARE(expr.evaluate(), QVariant("Cat"));
 +
 +        object3.setStringProperty("Donkey");
 +        QCOMPARE(expr.changed, true);
 +        expr.changed = false;
 +        QCOMPARE(expr.evaluate(), QVariant("Donkey"));
 +    }
 +}
 +
 +void tst_qqmlecmascript::deferredProperties()
 +{
 +    QQmlComponent component(&engine, testFileUrl("deferredProperties.qml"));
 +    MyDeferredObject *object = 
 +        qobject_cast<MyDeferredObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->value(), 0);
 +    QVERIFY(object->objectProperty() == 0);
 +    QVERIFY(object->objectProperty2() != 0);
 +    qmlExecuteDeferred(object);
 +    QCOMPARE(object->value(), 10);
 +    QVERIFY(object->objectProperty() != 0);
 +    MyQmlObject *qmlObject = 
 +        qobject_cast<MyQmlObject *>(object->objectProperty());
 +    QVERIFY(qmlObject != 0);
 +    QCOMPARE(qmlObject->value(), 10);
 +    object->setValue(19);
 +    QCOMPARE(qmlObject->value(), 19);
 +
 +    delete object;
 +}
 +
 +// Check errors on deferred properties are correctly emitted
 +void tst_qqmlecmascript::deferredPropertiesErrors()
 +{
 +    QQmlComponent component(&engine, testFileUrl("deferredPropertiesErrors.qml"));
 +    MyDeferredObject *object = 
 +        qobject_cast<MyDeferredObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->value(), 0);
 +    QVERIFY(object->objectProperty() == 0);
 +    QVERIFY(object->objectProperty2() == 0);
 +
 +    QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject*";
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +
 +    qmlExecuteDeferred(object);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::extensionObjects()
 +{
 +    QQmlComponent component(&engine, testFileUrl("extensionObjects.qml"));
 +    MyExtendedObject *object = 
 +        qobject_cast<MyExtendedObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->baseProperty(), 13);
 +    QCOMPARE(object->coreProperty(), 9);
 +    object->setProperty("extendedProperty", QVariant(11));
 +    object->setProperty("baseExtendedProperty", QVariant(92));
 +    QCOMPARE(object->coreProperty(), 11);
 +    QCOMPARE(object->baseProperty(), 92);
 +
 +    MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
 +    QVERIFY(nested);
 +    QCOMPARE(nested->baseProperty(), 13);
 +    QCOMPARE(nested->coreProperty(), 9);
 +    nested->setProperty("extendedProperty", QVariant(11));
 +    nested->setProperty("baseExtendedProperty", QVariant(92));
 +    QCOMPARE(nested->coreProperty(), 11);
 +    QCOMPARE(nested->baseProperty(), 92);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::overrideExtensionProperties()
 +{
 +    QQmlComponent component(&engine, testFileUrl("extensionObjectsPropertyOverride.qml"));
 +    OverrideDefaultPropertyObject *object =
 +        qobject_cast<OverrideDefaultPropertyObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QVERIFY(object->secondProperty() != 0);
 +    QVERIFY(object->firstProperty() == 0);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::attachedProperties()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("attachedProperty.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->property("a").toInt(), 19);
 +        QCOMPARE(object->property("b").toInt(), 19);
 +        QCOMPARE(object->property("c").toInt(), 19);
 +        QCOMPARE(object->property("d").toInt(), 19);
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("attachedProperty.2.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->property("a").toInt(), 26);
 +        QCOMPARE(object->property("b").toInt(), 26);
 +        QCOMPARE(object->property("c").toInt(), 26);
 +        QCOMPARE(object->property("d").toInt(), 26);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("writeAttachedProperty.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QMetaObject::invokeMethod(object, "writeValue2");
 +
 +        MyQmlAttachedObject *attached =
 +            qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
 +        QVERIFY(attached != 0);
 +
 +        QCOMPARE(attached->value2(), 9);
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::enums()
 +{
 +    // Existent enums
 +    {
 +    QQmlComponent component(&engine, testFileUrl("enums.1.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("a").toInt(), 0);
 +    QCOMPARE(object->property("b").toInt(), 1);
 +    QCOMPARE(object->property("c").toInt(), 2);
 +    QCOMPARE(object->property("d").toInt(), 3);
 +    QCOMPARE(object->property("e").toInt(), 0);
 +    QCOMPARE(object->property("f").toInt(), 1);
 +    QCOMPARE(object->property("g").toInt(), 2);
 +    QCOMPARE(object->property("h").toInt(), 3);
 +    QCOMPARE(object->property("i").toInt(), 19);
 +    QCOMPARE(object->property("j").toInt(), 19);
 +
 +    delete object;
 +    }
 +    // Non-existent enums
 +    {
 +    QQmlComponent component(&engine, testFileUrl("enums.2.qml"));
 +
 +    QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int";
 +    QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int";
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->property("a").toInt(), 0);
 +    QCOMPARE(object->property("b").toInt(), 0);
 +
 +    delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::valueTypeFunctions()
 +{
 +    QQmlComponent component(&engine, testFileUrl("valueTypeFunctions.qml"));
 +    MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
 +    QVERIFY(obj != 0);
 +    QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
 +    QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
 +
 +    delete obj;
 +}
 +
 +/* 
 +Tests that writing a constant to a property with a binding on it disables the
 +binding.
 +*/
 +void tst_qqmlecmascript::constantsOverrideBindings()
 +{
 +    // From ECMAScript
 +    {
 +        QQmlComponent component(&engine, testFileUrl("constantsOverrideBindings.1.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("c2").toInt(), 0);
 +        object->setProperty("c1", QVariant(9));
 +        QCOMPARE(object->property("c2").toInt(), 9);
 +
 +        emit object->basicSignal();
 +
 +        QCOMPARE(object->property("c2").toInt(), 13);
 +        object->setProperty("c1", QVariant(8));
 +        QCOMPARE(object->property("c2").toInt(), 13);
 +
 +        delete object;
 +    }
 +
 +    // During construction
 +    {
 +        QQmlComponent component(&engine, testFileUrl("constantsOverrideBindings.2.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("c1").toInt(), 0);
 +        QCOMPARE(object->property("c2").toInt(), 10);
 +        object->setProperty("c1", QVariant(9));
 +        QCOMPARE(object->property("c1").toInt(), 9);
 +        QCOMPARE(object->property("c2").toInt(), 10);
 +
 +        delete object;
 +    }
 +
 +#if 0
 +    // From C++
 +    {
 +        QQmlComponent component(&engine, testFileUrl("constantsOverrideBindings.3.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("c2").toInt(), 0);
 +        object->setProperty("c1", QVariant(9));
 +        QCOMPARE(object->property("c2").toInt(), 9);
 +
 +        object->setProperty("c2", QVariant(13));
 +        QCOMPARE(object->property("c2").toInt(), 13);
 +        object->setProperty("c1", QVariant(7));
 +        QCOMPARE(object->property("c1").toInt(), 7);
 +        QCOMPARE(object->property("c2").toInt(), 13);
 +
 +        delete object;
 +    }
 +#endif
 +
 +    // Using an alias
 +    {
 +        QQmlComponent component(&engine, testFileUrl("constantsOverrideBindings.4.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("c1").toInt(), 0);
 +        QCOMPARE(object->property("c3").toInt(), 10);
 +        object->setProperty("c1", QVariant(9));
 +        QCOMPARE(object->property("c1").toInt(), 9);
 +        QCOMPARE(object->property("c3").toInt(), 10);
 +
 +        delete object;
 +    }
 +}
 +
 +/*
 +Tests that assigning a binding to a property that already has a binding causes
 +the original binding to be disabled.
 +*/
 +void tst_qqmlecmascript::outerBindingOverridesInnerBinding()
 +{
 +    QQmlComponent component(&engine, 
 +                           testFileUrl("outerBindingOverridesInnerBinding.qml"));
 +    MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("c1").toInt(), 0);
 +    QCOMPARE(object->property("c2").toInt(), 0);
 +    QCOMPARE(object->property("c3").toInt(), 0);
 +
 +    object->setProperty("c1", QVariant(9));
 +    QCOMPARE(object->property("c1").toInt(), 9);
 +    QCOMPARE(object->property("c2").toInt(), 0);
 +    QCOMPARE(object->property("c3").toInt(), 0);
 +
 +    object->setProperty("c3", QVariant(8));
 +    QCOMPARE(object->property("c1").toInt(), 9);
 +    QCOMPARE(object->property("c2").toInt(), 8);
 +    QCOMPARE(object->property("c3").toInt(), 8);
 +
 +    delete object;
 +}
 +
 +/*
 +Access a non-existent attached object.  
 +
 +Tests for a regression where this used to crash.
 +*/
 +void tst_qqmlecmascript::nonExistentAttachedObject()
 +{
 +    QQmlComponent component(&engine, testFileUrl("nonExistentAttachedObject.qml"));
 +
 +    QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString";
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::scope()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scope.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test1").toInt(), 1);
 +        QCOMPARE(object->property("test2").toInt(), 2);
 +        QCOMPARE(object->property("test3").toString(), QString("1Test"));
 +        QCOMPARE(object->property("test4").toString(), QString("2Test"));
 +        QCOMPARE(object->property("test5").toInt(), 1);
 +        QCOMPARE(object->property("test6").toInt(), 1);
 +        QCOMPARE(object->property("test7").toInt(), 2);
 +        QCOMPARE(object->property("test8").toInt(), 2);
 +        QCOMPARE(object->property("test9").toInt(), 1);
 +        QCOMPARE(object->property("test10").toInt(), 3);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scope.2.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test1").toInt(), 19);
 +        QCOMPARE(object->property("test2").toInt(), 19);
 +        QCOMPARE(object->property("test3").toInt(), 14);
 +        QCOMPARE(object->property("test4").toInt(), 14);
 +        QCOMPARE(object->property("test5").toInt(), 24);
 +        QCOMPARE(object->property("test6").toInt(), 24);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scope.3.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test1").toBool(), true);
 +        QCOMPARE(object->property("test2").toBool(), true);
 +        QCOMPARE(object->property("test3").toBool(), true);
 +
 +        delete object;
 +    }
 +
 +    // Signal argument scope
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scope.4.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test").toInt(), 0);
 +        QCOMPARE(object->property("test2").toString(), QString());
 +
 +        emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
 +
 +        QCOMPARE(object->property("test").toInt(), 13);
 +        QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scope.5.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test1").toBool(), true);
 +        QCOMPARE(object->property("test2").toBool(), true);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scope.6.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +// In 4.7, non-library javascript files that had no imports shared the imports of their
 +// importing context
 +void tst_qqmlecmascript::importScope()
 +{
 +    QQmlComponent component(&engine, testFileUrl("importScope.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test").toInt(), 240);
 +
 +    delete o;
 +}
 +
 +/*
 +Tests that "any" type passes through a synthesized signal parameter.  This
 +is essentially a test of QQmlMetaType::copy()
 +*/
 +void tst_qqmlecmascript::signalParameterTypes()
 +{
 +    QQmlComponent component(&engine, testFileUrl("signalParameterTypes.qml"));
 +    MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    emit object->basicSignal();
 +
 +    QCOMPARE(object->property("intProperty").toInt(), 10);
 +    QCOMPARE(object->property("realProperty").toReal(), 19.2);
 +    QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
 +    QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
 +    QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
 +    QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
 +
 +    delete object;
 +}
 +
 +/*
 +Test that two JS objects for the same QObject compare as equal.
 +*/
 +void tst_qqmlecmascript::objectsCompareAsEqual()
 +{
 +    QQmlComponent component(&engine, testFileUrl("objectsCompareAsEqual.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test1").toBool(), true);
 +    QCOMPARE(object->property("test2").toBool(), true);
 +    QCOMPARE(object->property("test3").toBool(), true);
 +    QCOMPARE(object->property("test4").toBool(), true);
 +    QCOMPARE(object->property("test5").toBool(), true);
 +
 +    delete object;
 +}
 +
 +/*
 +Confirm bindings and alias properties can coexist.
 +
 +Tests for a regression where the binding would not reevaluate.
 +*/
 +void tst_qqmlecmascript::aliasPropertyAndBinding()
 +{
 +    QQmlComponent component(&engine, testFileUrl("aliasPropertyAndBinding.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("c2").toInt(), 3);
 +    QCOMPARE(object->property("c3").toInt(), 3);
 +
 +    object->setProperty("c2", QVariant(19));
 +
 +    QCOMPARE(object->property("c2").toInt(), 19);
 +    QCOMPARE(object->property("c3").toInt(), 19);
 +
 +    delete object;
 +}
 +
 +/*
 +Ensure that we can write undefined value to an alias property,
 +and that the aliased property is reset correctly if possible.
 +*/
 +void tst_qqmlecmascript::aliasPropertyReset()
 +{
 +    QObject *object = 0;
 +
 +    // test that a manual write (of undefined) to a resettable aliased property succeeds
 +    QQmlComponent c1(&engine, testFileUrl("aliasreset/aliasPropertyReset.1.qml"));
 +    object = c1.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() != 0);
 +    QCOMPARE(object->property("aliasIsUndefined"), QVariant(false));
 +    QMetaObject::invokeMethod(object, "resetAliased");
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0);
 +    QCOMPARE(object->property("aliasIsUndefined"), QVariant(true));
 +    delete object;
 +
 +    // test that a manual write (of undefined) to a resettable alias property succeeds
 +    QQmlComponent c2(&engine, testFileUrl("aliasreset/aliasPropertyReset.2.qml"));
 +    object = c2.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() != 0);
 +    QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(false));
 +    QMetaObject::invokeMethod(object, "resetAlias");
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0);
 +    QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(true));
 +    delete object;
 +
 +    // test that an alias to a bound property works correctly
 +    QQmlComponent c3(&engine, testFileUrl("aliasreset/aliasPropertyReset.3.qml"));
 +    object = c3.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() != 0);
 +    QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(false));
 +    QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
 +    QMetaObject::invokeMethod(object, "resetAlias");
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0);
 +    QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(true));
 +    QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
 +    delete object;
 +
 +    // test that a manual write (of undefined) to a resettable alias property
 +    // whose aliased property's object has been deleted, does not crash.
 +    QQmlComponent c4(&engine, testFileUrl("aliasreset/aliasPropertyReset.4.qml"));
 +    object = c4.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() != 0);
 +    QObject *loader = object->findChild<QObject*>("loader");
 +    QVERIFY(loader != 0);
 +    delete loader;
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0); // deletion should have caused value unset.
 +    QMetaObject::invokeMethod(object, "resetAlias"); // shouldn't crash.
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0);
 +    QMetaObject::invokeMethod(object, "setAlias");   // shouldn't crash, and shouldn't change value (since it's no longer referencing anything).
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0);
 +    delete object;
 +
 +    // test that binding an alias property to an undefined value works correctly
 +    QQmlComponent c5(&engine, testFileUrl("aliasreset/aliasPropertyReset.5.qml"));
 +    object = c5.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(object->property("sourceComponentAlias").value<QQmlComponent*>() == 0); // bound to undefined value.
 +    delete object;
 +
 +    // test that a manual write (of undefined) to a non-resettable property fails properly
 +    QUrl url = testFileUrl("aliasreset/aliasPropertyReset.error.1.qml");
 +    QString warning1 = url.toString() + QLatin1String(":15: Error: Cannot assign [undefined] to int");
 +    QQmlComponent e1(&engine, url);
 +    object = e1.create();
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->property("intAlias").value<int>(), 12);
 +    QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
 +    QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
 +    QMetaObject::invokeMethod(object, "resetAlias");
 +    QCOMPARE(object->property("intAlias").value<int>(), 12);
 +    QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::dynamicCreation_data()
 +{
 +    QTest::addColumn<QString>("method");
 +    QTest::addColumn<QString>("createdName");
 +
 +    QTest::newRow("One") << "createOne" << "objectOne";
 +    QTest::newRow("Two") << "createTwo" << "objectTwo";
 +    QTest::newRow("Three") << "createThree" << "objectThree";
 +}
 +
 +/*
 +Test using createQmlObject to dynamically generate an item
 +Also using createComponent is tested.
 +*/
 +void tst_qqmlecmascript::dynamicCreation()
 +{
 +    QFETCH(QString, method);
 +    QFETCH(QString, createdName);
 +
 +    QQmlComponent component(&engine, testFileUrl("dynamicCreation.qml"));
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QMetaObject::invokeMethod(object, method.toUtf8());
 +    QObject *created = object->objectProperty();
 +    QVERIFY(created);
 +    QCOMPARE(created->objectName(), createdName);
 +
 +    delete object;
 +}
 +
 +/*
 +   Tests the destroy function
 +*/
 +void tst_qqmlecmascript::dynamicDestruction()
 +{
 +    {
 +    QQmlComponent component(&engine, testFileUrl("dynamicDeletion.qml"));
 +    QQmlGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +    QQmlGuard<QObject> createdQmlObject = 0;
 +
 +    QMetaObject::invokeMethod(object, "create");
 +    createdQmlObject = object->objectProperty();
 +    QVERIFY(createdQmlObject);
 +    QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
 +
 +    QMetaObject::invokeMethod(object, "killOther");
 +    QVERIFY(createdQmlObject);
 +
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +    QCoreApplication::processEvents();
 +    QVERIFY(createdQmlObject);
 +    for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
 +        if (createdQmlObject) {
 +            QTest::qWait(100);
 +            QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +            QCoreApplication::processEvents();
 +        }
 +    }
 +    QVERIFY(!createdQmlObject);
 +
 +    QQmlEngine::setObjectOwnership(object, QQmlEngine::JavaScriptOwnership);
 +    QMetaObject::invokeMethod(object, "killMe");
 +    QVERIFY(object);
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +    QCoreApplication::processEvents();
 +    QVERIFY(!object);
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("dynamicDeletion.2.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
 +
 +    QMetaObject::invokeMethod(o, "create");
 +
 +    QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) != 0);
 +
 +    QMetaObject::invokeMethod(o, "destroy");
 +
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +    QCoreApplication::processEvents();
 +
 +    QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
 +
 +    delete o;
 +    }
 +}
 +
 +/*
 +   tests that id.toString() works
 +*/
 +void tst_qqmlecmascript::objectToString()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qmlToString.qml"));
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "testToString");
 +    QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
 +    QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
 +
 +    delete object;
 +}
 +
 +/*
 +  tests that id.hasOwnProperty() works
 +*/
 +void tst_qqmlecmascript::objectHasOwnProperty()
 +{
 +    QUrl url = testFileUrl("qmlHasOwnProperty.qml");
 +    QString warning1 = url.toString() + ":59: TypeError: Cannot call method 'hasOwnProperty' of undefined";
 +    QString warning2 = url.toString() + ":64: TypeError: Cannot call method 'hasOwnProperty' of undefined";
 +    QString warning3 = url.toString() + ":69: TypeError: Cannot call method 'hasOwnProperty' of undefined";
 +
 +    QQmlComponent component(&engine, url);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    // test QObjects in QML
 +    QMetaObject::invokeMethod(object, "testHasOwnPropertySuccess");
 +    QVERIFY(object->property("result").value<bool>() == true);
 +    QMetaObject::invokeMethod(object, "testHasOwnPropertyFailure");
 +    QVERIFY(object->property("result").value<bool>() == false);
 +
 +    // now test other types in QML
 +    QObject *child = object->findChild<QObject*>("typeObj");
 +    QVERIFY(child != 0);
 +    QMetaObject::invokeMethod(child, "testHasOwnPropertySuccess");
 +    QCOMPARE(child->property("valueTypeHasOwnProperty").toBool(), true);
 +    QCOMPARE(child->property("valueTypeHasOwnProperty2").toBool(), true);
 +    QCOMPARE(child->property("variantTypeHasOwnProperty").toBool(), true);
 +    QCOMPARE(child->property("stringTypeHasOwnProperty").toBool(), true);
 +    QCOMPARE(child->property("listTypeHasOwnProperty").toBool(), true);
 +    QCOMPARE(child->property("emptyListTypeHasOwnProperty").toBool(), true);
 +    QCOMPARE(child->property("enumTypeHasOwnProperty").toBool(), true);
 +    QCOMPARE(child->property("typenameHasOwnProperty").toBool(), true);
 +    QCOMPARE(child->property("typenameHasOwnProperty2").toBool(), true);
 +    QCOMPARE(child->property("moduleApiTypeHasOwnProperty").toBool(), true);
 +    QCOMPARE(child->property("moduleApiPropertyTypeHasOwnProperty").toBool(), true);
 +
 +    QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
 +    QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureOne");
 +    QCOMPARE(child->property("enumNonValueHasOwnProperty").toBool(), false);
 +    QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
 +    QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureTwo");
 +    QCOMPARE(child->property("moduleApiNonPropertyHasOwnProperty").toBool(), false);
 +    QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
 +    QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureThree");
 +    QCOMPARE(child->property("listAtInvalidHasOwnProperty").toBool(), false);
 +
 +    delete object;
 +}
 +
 +/*
 +Tests bindings that indirectly cause their own deletion work.
 +
 +This test is best run under valgrind to ensure no invalid memory access occur.
 +*/
 +void tst_qqmlecmascript::selfDeletingBinding()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("selfDeletingBinding.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        object->setProperty("triggerDelete", true);
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("selfDeletingBinding.2.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        object->setProperty("triggerDelete", true);
 +        delete object;
 +    }
 +}
 +
 +/*
 +Test that extended object properties can be accessed.
 +
 +This test a regression where this used to crash.  The issue was specificially
 +for extended objects that did not include a synthesized meta object (so non-root
 +and no synthesiszed properties).
 +*/
 +void tst_qqmlecmascript::extendedObjectPropertyLookup()
 +{
 +    QQmlComponent component(&engine, testFileUrl("extendedObjectPropertyLookup.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    delete object;
 +}
 +
 +/*
 +Test that extended object properties can be accessed correctly.
 +*/
 +void tst_qqmlecmascript::extendedObjectPropertyLookup2()
 +{
 +    QQmlComponent component(&engine, testFileUrl("extendedObjectPropertyLookup2.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QVariant returnValue;
 +    QVERIFY(QMetaObject::invokeMethod(object, "getValue", Q_RETURN_ARG(QVariant, returnValue)));
 +    QCOMPARE(returnValue.toInt(), 42);
 +
 +    delete object;
 +}
 +/*
 +Test file/lineNumbers for binding/Script errors.
 +*/
 +void tst_qqmlecmascript::scriptErrors()
 +{
 +    QQmlComponent component(&engine, testFileUrl("scriptErrors.qml"));
 +    QString url = component.url().toString();
 +
 +    QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
 +    QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
 +    QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
 +    QString warning4 = url + ":13: ReferenceError: Can't find variable: a";
 +    QString warning5 = url + ":11: ReferenceError: Can't find variable: a";
 +    QString warning6 = url + ":10: Unable to assign [undefined] to int";
 +    QString warning7 = url + ":15: Error: Cannot assign to read-only property \"trueProperty\"";
 +    QString warning8 = url + ":16: Error: Cannot assign to non-existent property \"fakeProperty\"";
 +
 +    QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
 +    QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
 +    QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
 +    QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
 +    QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
 +    MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
 +    emit object->basicSignal();
 +
 +    QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
 +    emit object->anotherBasicSignal();
 +
 +    QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
 +    emit object->thirdBasicSignal();
 +
 +    delete object;
 +}
 +
 +/*
 +Test file/lineNumbers for inline functions.
 +*/
 +void tst_qqmlecmascript::functionErrors()
 +{
 +    QQmlComponent component(&engine, testFileUrl("functionErrors.qml"));
 +    QString url = component.url().toString();
 +
 +    QString warning = url + ":5: Error: Invalid write to global property \"a\"";
 +
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    delete object;
 +
 +    // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
 +    QQmlComponent componentTwo(&engine, testFileUrl("scarceResourceFunctionFail.var.qml"));
 +    url = componentTwo.url().toString();
 +    object = componentTwo.create();
 +    QVERIFY(object != 0);
 +
 +    QString srpname = object->property("srp_name").toString();
 +    
 +    warning = url + QLatin1String(":16: TypeError: Property 'scarceResource' of object ") + srpname
 +                  + QLatin1String(" is not a function");
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
 +    QMetaObject::invokeMethod(object, "retrieveScarceResource");
 +    delete object;
 +}
 +
 +/*
 +Test various errors that can occur when assigning a property from script
 +*/
 +void tst_qqmlecmascript::propertyAssignmentErrors()
 +{
 +    QQmlComponent component(&engine, testFileUrl("propertyAssignmentErrors.qml"));
 +
 +    QString url = component.url().toString();
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test1").toBool(), true);
 +    QCOMPARE(object->property("test2").toBool(), true);
 +
 +    delete object;
 +}
 +    
 +/*
 +Test bindings still work when the reeval is triggered from within
 +a signal script.
 +*/
 +void tst_qqmlecmascript::signalTriggeredBindings()
 +{
 +    QQmlComponent component(&engine, testFileUrl("signalTriggeredBindings.qml"));
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("base").toReal(), 50.);
 +    QCOMPARE(object->property("test1").toReal(), 50.);
 +    QCOMPARE(object->property("test2").toReal(), 50.);
 +
 +    object->basicSignal();
 +
 +    QCOMPARE(object->property("base").toReal(), 200.);
 +    QCOMPARE(object->property("test1").toReal(), 200.);
 +    QCOMPARE(object->property("test2").toReal(), 200.);
 +
 +    object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
 +
 +    QCOMPARE(object->property("base").toReal(), 400.);
 +    QCOMPARE(object->property("test1").toReal(), 400.);
 +    QCOMPARE(object->property("test2").toReal(), 400.);
 +
 +    delete object;
 +}
 +
 +/*
 +Test that list properties can be iterated from ECMAScript
 +*/
 +void tst_qqmlecmascript::listProperties()
 +{
 +    QQmlComponent component(&engine, testFileUrl("listProperties.qml"));
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test1").toInt(), 21);
 +    QCOMPARE(object->property("test2").toInt(), 2);
 +    QCOMPARE(object->property("test3").toBool(), true);
 +    QCOMPARE(object->property("test4").toBool(), true);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::exceptionClearsOnReeval()
 +{
 +    QQmlComponent component(&engine, testFileUrl("exceptionClearsOnReeval.qml"));
 +    QString url = component.url().toString();
 +
 +    QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
 +
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), false);
 +
 +    MyQmlObject object2;
 +    MyQmlObject object3;
 +    object2.setObjectProperty(&object3);
 +    object->setObjectProperty(&object2);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::exceptionSlotProducesWarning()
 +{
 +    QQmlComponent component(&engine, testFileUrl("exceptionProducesWarning.qml"));
 +    QString url = component.url().toString();
 +
 +    QString warning = component.url().toString() + ":6: Error: JS exception";
 +
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::exceptionBindingProducesWarning()
 +{
 +    QQmlComponent component(&engine, testFileUrl("exceptionProducesWarning2.qml"));
 +    QString url = component.url().toString();
 +
 +    QString warning = component.url().toString() + ":5: Error: JS exception";
 +
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::compileInvalidBinding()
 +{
 +    // QTBUG-23387: ensure that invalid bindings don't cause a crash.
 +    QQmlComponent component(&engine, testFileUrl("v8bindingException.qml"));
-     // QTBUG-23387
-     QQmlComponent component(&engine, testFileUrl("rewriteMultiLineStrings.qml"));
-     QObject *o = component.create();
-     QVERIFY(o != 0);
-     QTRY_COMPARE(o->property("test").toBool(), true);
-     delete o;
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    delete object;
 +}
 +
 +static int transientErrorsMsgCount = 0;
 +static void transientErrorsMsgHandler(QtMsgType, const char *)
 +{
 +    ++transientErrorsMsgCount;
 +}
 +
 +// Check that transient binding errors are not displayed
 +void tst_qqmlecmascript::transientErrors()
 +{
 +    {
 +    QQmlComponent component(&engine, testFileUrl("transientErrors.qml"));
 +
 +    transientErrorsMsgCount = 0;
 +    QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    qInstallMsgHandler(old);
 +
 +    QCOMPARE(transientErrorsMsgCount, 0);
 +
 +    delete object;
 +    }
 +
 +    // One binding erroring multiple times, but then resolving
 +    {
 +    QQmlComponent component(&engine, testFileUrl("transientErrors.2.qml"));
 +
 +    transientErrorsMsgCount = 0;
 +    QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    qInstallMsgHandler(old);
 +
 +    QCOMPARE(transientErrorsMsgCount, 0);
 +
 +    delete object;
 +    }
 +}
 +
 +// Check that errors during shutdown are minimized
 +void tst_qqmlecmascript::shutdownErrors()
 +{
 +    QQmlComponent component(&engine, testFileUrl("shutdownErrors.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    transientErrorsMsgCount = 0;
 +    QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
 +
 +    delete object;
 +
 +    qInstallMsgHandler(old);
 +    QCOMPARE(transientErrorsMsgCount, 0);
 +}
 +
 +void tst_qqmlecmascript::compositePropertyType()
 +{
 +    QQmlComponent component(&engine, testFileUrl("compositePropertyType.qml"));
 +
 +    QTest::ignoreMessage(QtDebugMsg, "hello world");
 +    QObject *object = qobject_cast<QObject *>(component.create());
 +    delete object;
 +}
 +
 +// QTBUG-5759
 +void tst_qqmlecmascript::jsObject()
 +{
 +    QQmlComponent component(&engine, testFileUrl("jsObject.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toInt(), 92);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::undefinedResetsProperty()
 +{
 +    {
 +    QQmlComponent component(&engine, testFileUrl("undefinedResetsProperty.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("resettableProperty").toInt(), 92);
 +
 +    object->setProperty("setUndefined", true);
 +
 +    QCOMPARE(object->property("resettableProperty").toInt(), 13);
 +
 +    object->setProperty("setUndefined", false);
 +
 +    QCOMPARE(object->property("resettableProperty").toInt(), 92);
 +
 +    delete object;
 +    }
 +    {
 +    QQmlComponent component(&engine, testFileUrl("undefinedResetsProperty.2.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("resettableProperty").toInt(), 19);
 +
 +    QMetaObject::invokeMethod(object, "doReset");
 +
 +    QCOMPARE(object->property("resettableProperty").toInt(), 13);
 +
 +    delete object;
 +    }
 +}
 +
 +// Aliases to variant properties should work
 +void tst_qqmlecmascript::qtbug_22464()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtbug_22464.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::qtbug_21580()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtbug_21580.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +}
 +
 +// QTBUG-6781
 +void tst_qqmlecmascript::bug1()
 +{
 +    QQmlComponent component(&engine, testFileUrl("bug.1.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toInt(), 14);
 +
 +    object->setProperty("a", 11);
 +
 +    QCOMPARE(object->property("test").toInt(), 3);
 +
 +    object->setProperty("b", true);
 +
 +    QCOMPARE(object->property("test").toInt(), 9);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::bug2()
 +{
 +    QQmlComponent component(&engine);
 +    component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    delete object;
 +}
 +
 +// Don't crash in createObject when the component has errors.
 +void tst_qqmlecmascript::dynamicCreationCrash()
 +{
 +    QQmlComponent component(&engine, testFileUrl("dynamicCreation.qml"));
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
 +    QMetaObject::invokeMethod(object, "dontCrash");
 +    QObject *created = object->objectProperty();
 +    QVERIFY(created == 0);
 +
 +    delete object;
 +}
 +
 +// ownership transferred to JS, ensure that GC runs the dtor
 +void tst_qqmlecmascript::dynamicCreationOwnership()
 +{
 +    int dtorCount = 0;
 +    int expectedDtorCount = 1; // start at 1 since we expect mdcdo to dtor too.
 +
 +    // allow the engine to go out of scope too.
 +    {
 +        QQmlEngine dcoEngine;
 +        QQmlComponent component(&dcoEngine, testFileUrl("dynamicCreationOwnership.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        MyDynamicCreationDestructionObject *mdcdo = object->findChild<MyDynamicCreationDestructionObject*>("mdcdo");
 +        QVERIFY(mdcdo != 0);
 +        mdcdo->setDtorCount(&dtorCount);
 +
 +        for (int i = 1; i < 105; ++i, ++expectedDtorCount) {
 +            QMetaObject::invokeMethod(object, "dynamicallyCreateJsOwnedObject");
 +            if (i % 90 == 0) {
 +                // we do this once manually, but it should be done automatically
 +                // when the engine goes out of scope (since it should gc in dtor)
 +                QMetaObject::invokeMethod(object, "performGc");
 +            }
 +            if (i % 10 == 0) {
 +                QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +                QCoreApplication::processEvents();
 +            }
 +        }
 +
 +        delete object;
 +    }
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +    QCoreApplication::processEvents();
 +    QCOMPARE(dtorCount, expectedDtorCount);
 +}
 +
 +void tst_qqmlecmascript::regExpBug()
 +{
 +    //QTBUG-9367
 +    {
 +        QQmlComponent component(&engine, testFileUrl("regExp.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
 +        delete object;
 +    }
 +
 +    //QTBUG-23068
 +    {
 +        QString err = QString(QLatin1String("%1:6 Invalid property assignment: regular expression expected; use /pattern/ syntax\n")).arg(testFileUrl("regExp.2.qml").toString());
 +        QQmlComponent component(&engine, testFileUrl("regExp.2.qml"));
 +        QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
 +        MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +        QVERIFY(!object);
 +        QCOMPARE(component.errorString(), err);
 +    }
 +}
 +
 +static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
 +{
 +    QString functionSource = QLatin1String("(function(object) { return ") + 
 +                             QLatin1String(source) + QLatin1String(" })");
 +    v8::TryCatch tc;
 +    v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
 +    if (tc.HasCaught())
 +        return false;
 +    v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
 +    if (function.IsEmpty())
 +        return false;
 +    v8::Handle<v8::Value> args[] = { o };
 +    function->Call(engine->global(), 1, args);
 +    return tc.HasCaught();
 +}
 +
 +static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o, 
 +                                  const char *source, v8::Handle<v8::Value> result)
 +{
 +    QString functionSource = QLatin1String("(function(object) { return ") + 
 +                             QLatin1String(source) + QLatin1String(" })");
 +    v8::TryCatch tc;
 +    v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
 +    if (tc.HasCaught())
 +        return false;
 +    v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
 +    if (function.IsEmpty())
 +        return false;
 +    v8::Handle<v8::Value> args[] = { o };
 +
 +    v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
 +
 +    if (tc.HasCaught())
 +        return false;
 +
 +    return value->StrictEquals(result);
 +}
 +
 +static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o, 
 +                                             const char *source)
 +{
 +    QString functionSource = QLatin1String("(function(object) { return ") + 
 +                             QLatin1String(source) + QLatin1String(" })");
 +    v8::TryCatch tc;
 +    v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
 +    if (tc.HasCaught())
 +        return v8::Handle<v8::Value>();
 +    v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
 +    if (function.IsEmpty())
 +        return v8::Handle<v8::Value>();
 +    v8::Handle<v8::Value> args[] = { o };
 +
 +    v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
 +
 +    if (tc.HasCaught())
 +        return v8::Handle<v8::Value>();
 +    return value;
 +}
 +
 +#define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
 +#define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
 +#define EVALUATE(source) evaluate(engine, object, source)
 +
 +void tst_qqmlecmascript::callQtInvokables()
 +{
 +    MyInvokableObject o;
 +
 +    QQmlEngine qmlengine;
 +    QQmlEnginePrivate *ep = QQmlEnginePrivate::get(&qmlengine);
 +    
 +    QV8Engine *engine = ep->v8engine();
 +
 +    v8::HandleScope handle_scope;
 +    v8::Context::Scope scope(engine->context());
 +
 +    v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
 +
 +    // Non-existent methods
 +    o.reset();
 +    QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), -1);
 +    QCOMPARE(o.actuals().count(), 0);
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), -1);
 +    QCOMPARE(o.actuals().count(), 0);
 +
 +    // Insufficient arguments
 +    o.reset();
 +    QVERIFY(EVALUATE_ERROR("object.method_int()"));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), -1);
 +    QCOMPARE(o.actuals().count(), 0);
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), -1);
 +    QCOMPARE(o.actuals().count(), 0);
 +
 +    // Excessive arguments
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 8);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(10));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 9);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(10));
 +    QCOMPARE(o.actuals().at(1), QVariant(11));
 +
 +    // Test return types
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 0);
 +    QCOMPARE(o.actuals().count(), 0);
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 1);
 +    QCOMPARE(o.actuals().count(), 0);
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 2);
 +    QCOMPARE(o.actuals().count(), 0);
 +
 +    o.reset();
 +    {
 +    v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
 +    QVERIFY(!ret.IsEmpty());
 +    QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 3);
 +    QCOMPARE(o.actuals().count(), 0);
 +    }
 +
 +    o.reset();
 +    {
 +    v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
 +    QCOMPARE(engine->toQObject(ret), (QObject *)&o);
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 4);
 +    QCOMPARE(o.actuals().count(), 0);
 +    }
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 5);
 +    QCOMPARE(o.actuals().count(), 0);
 +
 +    o.reset();
 +    {
 +    v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
 +    QVERIFY(ret->IsString());
 +    QCOMPARE(engine->toString(ret), QString("Hello world"));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 6);
 +    QCOMPARE(o.actuals().count(), 0);
 +    }
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 7);
 +    QCOMPARE(o.actuals().count(), 0);
 +
 +    // Test arg types
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 8);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(94));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 8);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(94));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 8);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(0));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 8);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(0));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 8);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(0));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 8);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(0));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 9);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(122));
 +    QCOMPARE(o.actuals().at(1), QVariant(9));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 10);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(94.3));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 10);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(94.3));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 10);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 10);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(0));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 10);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 10);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 11);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 11);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant("19"));
 +
 +    o.reset();
 +    {
 +    QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
 +    QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 11);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(expected));
 +    }
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 11);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(QString()));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 11);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(QString()));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 12);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 12);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 12);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 12);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 12);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 12);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 13);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 13);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 13);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 13);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 13);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 14);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isNull());
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 14);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isUndefined());
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 14);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).strictlyEquals(QJSValue(19)));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 14);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isArray());
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 15);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(4));
 +    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isNull());
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 15);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(8));
 +    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isUndefined());
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 15);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(3));
 +    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).strictlyEquals(QJSValue(19)));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 15);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(44));
 +    QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isArray());
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_ERROR("object.method_overload()"));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), -1);
 +    QCOMPARE(o.actuals().count(), 0);
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 16);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(10));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 17);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(10));
 +    QCOMPARE(o.actuals().at(1), QVariant(11));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 18);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 19);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(9));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 20);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(10));
 +    QCOMPARE(o.actuals().at(1), QVariant(19));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 20);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(10));
 +    QCOMPARE(o.actuals().at(1), QVariant(13));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), -3);
 +    QCOMPARE(o.actuals().count(), 1);
 +    QCOMPARE(o.actuals().at(0), QVariant(9));
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 21);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(9));
 +    QCOMPARE(o.actuals().at(1), QVariant());
 +
 +    o.reset();
 +    QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
 +    QCOMPARE(o.error(), false);
 +    QCOMPARE(o.invoked(), 21);
 +    QCOMPARE(o.actuals().count(), 2);
 +    QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
 +    QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
 +}
 +
 +// QTBUG-13047 (check that you can pass registered object types as args)
 +void tst_qqmlecmascript::invokableObjectArg()
 +{
 +    QQmlComponent component(&engine, testFileUrl("invokableObjectArg.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o);
 +    MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
 +    QVERIFY(qmlobject);
 +    QCOMPARE(qmlobject->myinvokableObject, qmlobject);
 +
 +    delete o;
 +}
 +
 +// QTBUG-13047 (check that you can return registered object types from methods)
 +void tst_qqmlecmascript::invokableObjectRet()
 +{
 +    QQmlComponent component(&engine, testFileUrl("invokableObjectRet.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o);
 +    QCOMPARE(o->property("test").toBool(), true);
 +    delete o;
 +}
 +
 +// QTBUG-5675
 +void tst_qqmlecmascript::listToVariant()
 +{
 +    QQmlComponent component(&engine, testFileUrl("listToVariant.qml"));
 +
 +    MyQmlContainer container;
 +
 +    QQmlContext context(engine.rootContext());
 +    context.setContextObject(&container);
 +
 +    QObject *object = component.create(&context);
 +    QVERIFY(object != 0);
 +
 +    QVariant v = object->property("test");
 +    QCOMPARE(v.userType(), qMetaTypeId<QQmlListReference>());
 +    QVERIFY(qvariant_cast<QQmlListReference>(v).object() == &container);
 +
 +    delete object;
 +}
 +
 +// QTBUG-16316
 +Q_DECLARE_METATYPE(QQmlListProperty<MyQmlObject>)
 +void tst_qqmlecmascript::listAssignment()
 +{
 +    QQmlComponent component(&engine, testFileUrl("listAssignment.qml"));
 +    QObject *obj = component.create();
 +    QCOMPARE(obj->property("list1length").toInt(), 2);
 +    QQmlListProperty<MyQmlObject> list1 = obj->property("list1").value<QQmlListProperty<MyQmlObject> >();
 +    QQmlListProperty<MyQmlObject> list2 = obj->property("list2").value<QQmlListProperty<MyQmlObject> >();
 +    QCOMPARE(list1.count(&list1), list2.count(&list2));
 +    QCOMPARE(list1.at(&list1, 0), list2.at(&list2, 0));
 +    QCOMPARE(list1.at(&list1, 1), list2.at(&list2, 1));
 +    delete obj;
 +}
 +
 +// QTBUG-7957
 +void tst_qqmlecmascript::multiEngineObject()
 +{
 +    MyQmlObject obj;
 +    obj.setStringProperty("Howdy planet");
 +
 +    QQmlEngine e1;
 +    e1.rootContext()->setContextProperty("thing", &obj);
 +    QQmlComponent c1(&e1, testFileUrl("multiEngineObject.qml"));
 +
 +    QQmlEngine e2;
 +    e2.rootContext()->setContextProperty("thing", &obj);
 +    QQmlComponent c2(&e2, testFileUrl("multiEngineObject.qml"));
 +
 +    QObject *o1 = c1.create();
 +    QObject *o2 = c2.create();
 +
 +    QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
 +    QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
 +
 +    delete o2;
 +    delete o1;
 +}
 +
 +// Test that references to QObjects are cleanup when the object is destroyed
 +void tst_qqmlecmascript::deletedObject()
 +{
 +    QQmlComponent component(&engine, testFileUrl("deletedObject.qml"));
 +
 +    QObject *object = component.create();
 +
 +    QCOMPARE(object->property("test1").toBool(), true);
 +    QCOMPARE(object->property("test2").toBool(), true);
 +    QCOMPARE(object->property("test3").toBool(), true);
 +    QCOMPARE(object->property("test4").toBool(), true);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::attachedPropertyScope()
 +{
 +    QQmlComponent component(&engine, testFileUrl("attachedPropertyScope.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    MyQmlAttachedObject *attached = 
 +        qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
 +    QVERIFY(attached != 0);
 +
 +    QCOMPARE(object->property("value2").toInt(), 0);
 +
 +    attached->emitMySignal();
 +
 +    QCOMPARE(object->property("value2").toInt(), 9);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::scriptConnect()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scriptConnect.1.qml"));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test").toBool(), false);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toBool(), true);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scriptConnect.2.qml"));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test").toBool(), false);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toBool(), true);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scriptConnect.3.qml"));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test").toBool(), false);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toBool(), true);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scriptConnect.4.qml"));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->methodCalled(), false);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->methodCalled(), true);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scriptConnect.5.qml"));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->methodCalled(), false);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->methodCalled(), true);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scriptConnect.6.qml"));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test").toInt(), 0);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 2);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::scriptDisconnect()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scriptDisconnect.1.qml"));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test").toInt(), 0);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 1);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 2);
 +        emit object->basicSignal();
 +        QCOMPARE(object->property("test").toInt(), 2);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 2);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scriptDisconnect.2.qml"));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test").toInt(), 0);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 1);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 2);
 +        emit object->basicSignal();
 +        QCOMPARE(object->property("test").toInt(), 2);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 2);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scriptDisconnect.3.qml"));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test").toInt(), 0);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 1);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 2);
 +        emit object->basicSignal();
 +        QCOMPARE(object->property("test").toInt(), 2);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 3);
 +
 +        delete object;
 +    }
 +    {
 +        QQmlComponent component(&engine, testFileUrl("scriptDisconnect.4.qml"));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("test").toInt(), 0);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 1);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 2);
 +        emit object->basicSignal();
 +        QCOMPARE(object->property("test").toInt(), 2);
 +        emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
 +        QCOMPARE(object->property("test").toInt(), 3);
 +
 +        delete object;
 +    }
 +}
 +
 +class OwnershipObject : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    OwnershipObject() { object = new QObject; }
 +
 +    QPointer<QObject> object;
 +
 +public slots:
 +    QObject *getObject() { return object; }
 +};
 +
 +void tst_qqmlecmascript::ownership()
 +{
 +    OwnershipObject own;
 +    QQmlContext *context = new QQmlContext(engine.rootContext());
 +    context->setContextObject(&own);
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("ownership.qml"));
 +
 +        QVERIFY(own.object != 0);
 +
 +        QObject *object = component.create(context);
 +
 +        engine.collectGarbage();
 +
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +
 +        QVERIFY(own.object == 0);
 +
 +        delete object;
 +    }
 +
 +    own.object = new QObject(&own);
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("ownership.qml"));
 +
 +        QVERIFY(own.object != 0);
 +
 +        QObject *object = component.create(context);
 +        
 +        engine.collectGarbage();
 +
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +
 +        QVERIFY(own.object != 0);
 +
 +        delete object;
 +    }
 +
 +    delete context;
 +}
 +
 +class CppOwnershipReturnValue : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    CppOwnershipReturnValue() : value(0) {}
 +    ~CppOwnershipReturnValue() { delete value; }
 +
 +    Q_INVOKABLE QObject *create() {
 +        value = new QObject;
 +        QQmlEngine::setObjectOwnership(value, QQmlEngine::CppOwnership);
 +        return value;
 +    }
 +
 +    Q_INVOKABLE MyQmlObject *createQmlObject() {
 +        MyQmlObject *rv = new MyQmlObject;
 +        value = rv;
 +        return rv;
 +    }
 +
 +    QPointer<QObject> value;
 +};
 +
 +// QTBUG-15695.  
 +// Test setObjectOwnership(CppOwnership) works even when there is no QQmlData
 +void tst_qqmlecmascript::cppOwnershipReturnValue()
 +{
 +    CppOwnershipReturnValue source;
 +
 +    {
 +    QQmlEngine engine;
 +    engine.rootContext()->setContextProperty("source", &source);
 +
 +    QVERIFY(source.value == 0);
 +
 +    QQmlComponent component(&engine);
 +    component.setData("import QtQuick 2.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
 +
 +    QObject *object = component.create();
 +
 +    QVERIFY(object != 0);
 +    QVERIFY(source.value != 0);
 +
 +    delete object;
 +    }
 +
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +    QCoreApplication::processEvents();
 +
 +    QVERIFY(source.value != 0);
 +}
 +
 +// QTBUG-15697
 +void tst_qqmlecmascript::ownershipCustomReturnValue()
 +{
 +    CppOwnershipReturnValue source;
 +
 +    {
 +    QQmlEngine engine;
 +    engine.rootContext()->setContextProperty("source", &source);
 +
 +    QVERIFY(source.value == 0);
 +
 +    QQmlComponent component(&engine);
 +    component.setData("import QtQuick 2.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
 +
 +    QObject *object = component.create();
 +
 +    QVERIFY(object != 0);
 +    QVERIFY(source.value != 0);
 +
 +    delete object;
 +    }
 +
 +    engine.collectGarbage();
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +    QCoreApplication::processEvents();
 +
 +    QVERIFY(source.value == 0);
 +}
 +
 +class QListQObjectMethodsObject : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    QListQObjectMethodsObject() {
 +        m_objects.append(new MyQmlObject());
 +        m_objects.append(new MyQmlObject());
 +    }
 +
 +    ~QListQObjectMethodsObject() {
 +        qDeleteAll(m_objects);
 +    }
 +
 +public slots:
 +    QList<QObject *> getObjects() { return m_objects; }
 +
 +private:
 +    QList<QObject *> m_objects;
 +};
 +
 +// Tests that returning a QList<QObject*> from a method works
 +void tst_qqmlecmascript::qlistqobjectMethods()
 +{
 +    QListQObjectMethodsObject obj;
 +    QQmlContext *context = new QQmlContext(engine.rootContext());
 +    context->setContextObject(&obj);
 +
 +    QQmlComponent component(&engine, testFileUrl("qlistqobjectMethods.qml"));
 +
 +    QObject *object = component.create(context);
 +
 +    QCOMPARE(object->property("test").toInt(), 2);
 +    QCOMPARE(object->property("test2").toBool(), true);
 +
 +    delete object;
 +    delete context;
 +}
 +
 +// QTBUG-9205
 +void tst_qqmlecmascript::strictlyEquals()
 +{
 +    QQmlComponent component(&engine, testFileUrl("strictlyEquals.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test1").toBool(), true);
 +    QCOMPARE(object->property("test2").toBool(), true);
 +    QCOMPARE(object->property("test3").toBool(), true);
 +    QCOMPARE(object->property("test4").toBool(), true);
 +    QCOMPARE(object->property("test5").toBool(), true);
 +    QCOMPARE(object->property("test6").toBool(), true);
 +    QCOMPARE(object->property("test7").toBool(), true);
 +    QCOMPARE(object->property("test8").toBool(), true);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::compiled()
 +{
 +    QQmlComponent component(&engine, testFileUrl("compiled.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test1").toReal(), qreal(15.7));
 +    QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
 +    QCOMPARE(object->property("test3").toBool(), true);
 +    QCOMPARE(object->property("test4").toBool(), false);
 +    QCOMPARE(object->property("test5").toBool(), false);
 +    QCOMPARE(object->property("test6").toBool(), true);
 +
 +    QCOMPARE(object->property("test7").toInt(), 185);
 +    QCOMPARE(object->property("test8").toInt(), 167);
 +    QCOMPARE(object->property("test9").toBool(), true);
 +    QCOMPARE(object->property("test10").toBool(), false);
 +    QCOMPARE(object->property("test11").toBool(), false);
 +    QCOMPARE(object->property("test12").toBool(), true);
 +
 +    QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
 +    QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
 +    QCOMPARE(object->property("test15").toBool(), false);
 +    QCOMPARE(object->property("test16").toBool(), true);
 +
 +    QCOMPARE(object->property("test17").toInt(), 5);
 +    QCOMPARE(object->property("test18").toReal(), qreal(176));
 +    QCOMPARE(object->property("test19").toInt(), 7);
 +    QCOMPARE(object->property("test20").toReal(), qreal(6.7));
 +    QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
 +    QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
 +    QCOMPARE(object->property("test23").toBool(), true);
 +    QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
 +    QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
 +
 +    delete object;
 +}
 +
 +// Test that numbers assigned in bindings as strings work consistently
 +void tst_qqmlecmascript::numberAssignment()
 +{
 +    QQmlComponent component(&engine, testFileUrl("numberAssignment.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
 +    QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
 +    QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
 +    QCOMPARE(object->property("test3"), QVariant((qreal)6));
 +    QCOMPARE(object->property("test4"), QVariant((qreal)6));
 +
 +    QCOMPARE(object->property("test5"), QVariant((int)7));
 +    QCOMPARE(object->property("test6"), QVariant((int)7));
 +    QCOMPARE(object->property("test7"), QVariant((int)6));
 +    QCOMPARE(object->property("test8"), QVariant((int)6));
 +
 +    QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
 +    QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
 +    QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
 +    QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::propertySplicing()
 +{
 +    QQmlComponent component(&engine, testFileUrl("propertySplicing.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +}
 +
 +// QTBUG-16683
 +void tst_qqmlecmascript::signalWithUnknownTypes()
 +{
 +    QQmlComponent component(&engine, testFileUrl("signalWithUnknownTypes.qml"));
 +
 +    MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    MyQmlObject::MyType type;
 +    type.value = 0x8971123;
 +    emit object->signalWithUnknownType(type);
 +
 +    MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
 +
 +    QCOMPARE(result.value, type.value);
 +
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::signalWithJSValueInVariant_data()
 +{
 +    QTest::addColumn<QString>("expression");
 +    QTest::addColumn<QString>("compare");
 +
 +    QString compareStrict("(function(a, b) { return a === b; })");
 +    QTest::newRow("true") << "true" << compareStrict;
 +    QTest::newRow("undefined") << "undefined" << compareStrict;
 +    QTest::newRow("null") << "null" << compareStrict;
 +    QTest::newRow("123") << "123" << compareStrict;
 +    QTest::newRow("'ciao'") << "'ciao'" << compareStrict;
 +
 +    QString comparePropertiesStrict(
 +        "(function(a, b) {"
 +        "  if (typeof b != 'object')"
 +        "    return a === b;"
 +        "  var props = Object.getOwnPropertyNames(b);"
 +        "  for (var i = 0; i < props.length; ++i) {"
 +        "    var p = props[i];"
 +        "    return arguments.callee(a[p], b[p]);"
 +        "  }"
 +        "})");
 +    QTest::newRow("{ foo: 'bar' }") << "({ foo: 'bar' })"  << comparePropertiesStrict;
 +    QTest::newRow("[10,20,30]") << "[10,20,30]"  << comparePropertiesStrict;
 +}
 +
 +void tst_qqmlecmascript::signalWithJSValueInVariant()
 +{
 +    QFETCH(QString, expression);
 +    QFETCH(QString, compare);
 +
 +    QQmlComponent component(&engine, testFileUrl("signalWithJSValueInVariant.qml"));
 +    QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject *>(component.create()));
 +    QVERIFY(object != 0);
 +
 +    QJSValue value = engine.evaluate(expression);
 +    QVERIFY(!engine.hasUncaughtException());
 +    object->setProperty("expression", expression);
 +    object->setProperty("compare", compare);
 +    object->setProperty("pass", false);
 +
 +    emit object->signalWithVariant(QVariant::fromValue(value));
 +    QVERIFY(object->property("pass").toBool());
 +}
 +
 +void tst_qqmlecmascript::signalWithJSValueInVariant_twoEngines_data()
 +{
 +    signalWithJSValueInVariant_data();
 +}
 +
 +void tst_qqmlecmascript::signalWithJSValueInVariant_twoEngines()
 +{
 +    QFETCH(QString, expression);
 +    QFETCH(QString, compare);
 +
 +    QQmlComponent component(&engine, testFileUrl("signalWithJSValueInVariant.qml"));
 +    QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject *>(component.create()));
 +    QVERIFY(object != 0);
 +
 +    QJSEngine engine2;
 +    QJSValue value = engine2.evaluate(expression);
 +    QVERIFY(!engine2.hasUncaughtException());
 +    object->setProperty("expression", expression);
 +    object->setProperty("compare", compare);
 +    object->setProperty("pass", false);
 +
 +    QTest::ignoreMessage(QtWarningMsg, "JSValue can't be rassigned to an another engine.");
 +    emit object->signalWithVariant(QVariant::fromValue(value));
 +    QVERIFY(!object->property("pass").toBool());
 +}
 +
 +void tst_qqmlecmascript::signalWithQJSValue_data()
 +{
 +    signalWithJSValueInVariant_data();
 +}
 +
 +void tst_qqmlecmascript::signalWithQJSValue()
 +{
 +    QFETCH(QString, expression);
 +    QFETCH(QString, compare);
 +
 +    QQmlComponent component(&engine, testFileUrl("signalWithQJSValue.qml"));
 +    QScopedPointer<MyQmlObject> object(qobject_cast<MyQmlObject *>(component.create()));
 +    QVERIFY(object != 0);
 +
 +    QJSValue value = engine.evaluate(expression);
 +    QVERIFY(!engine.hasUncaughtException());
 +    object->setProperty("expression", expression);
 +    object->setProperty("compare", compare);
 +    object->setProperty("pass", false);
 +
 +    emit object->signalWithQJSValue(value);
 +
 +    QVERIFY(object->property("pass").toBool());
 +    QVERIFY(object->qjsvalue().strictlyEquals(value));
 +}
 +
 +void tst_qqmlecmascript::moduleApi_data()
 +{
 +    QTest::addColumn<QUrl>("testfile");
 +    QTest::addColumn<QString>("errorMessage");
 +    QTest::addColumn<QStringList>("warningMessages");
 +    QTest::addColumn<QStringList>("readProperties");
 +    QTest::addColumn<QVariantList>("readExpectedValues");
 +    QTest::addColumn<QStringList>("writeProperties");
 +    QTest::addColumn<QVariantList>("writeValues");
 +    QTest::addColumn<QStringList>("readBackProperties");
 +    QTest::addColumn<QVariantList>("readBackExpectedValues");
 +
 +    QTest::newRow("qobject, register + read + method")
 +            << testFileUrl("moduleapi/qobjectModuleApi.qml")
 +            << QString()
 +            << QStringList()
 +            << (QStringList() << "existingUriTest" << "qobjectTest" << "qobjectMethodTest"
 +                   << "qobjectMinorVersionTest" << "qobjectMajorVersionTest" << "qobjectParentedTest")
 +            << (QVariantList() << 20 << 20 << 1 << 20 << 20 << 26)
 +            << QStringList()
 +            << QVariantList()
 +            << QStringList()
 +            << QVariantList();
 +
 +    QTest::newRow("script, register + read")
 +            << testFileUrl("moduleapi/scriptModuleApi.qml")
 +            << QString()
 +            << QStringList()
 +            << (QStringList() << "scriptTest")
 +            << (QVariantList() << 13)
 +            << QStringList()
 +            << QVariantList()
 +            << QStringList()
 +            << QVariantList();
 +
 +    QTest::newRow("qobject, caching + read")
 +            << testFileUrl("moduleapi/qobjectModuleApiCaching.qml")
 +            << QString()
 +            << QStringList()
 +            << (QStringList() << "existingUriTest" << "qobjectParentedTest")
 +            << (QVariantList() << 20 << 26) // 26, shouldn't have incremented to 27.
 +            << QStringList()
 +            << QVariantList()
 +            << QStringList()
 +            << QVariantList();
 +
 +    QTest::newRow("script, caching + read")
 +            << testFileUrl("moduleapi/scriptModuleApiCaching.qml")
 +            << QString()
 +            << QStringList()
 +            << (QStringList() << "scriptTest")
 +            << (QVariantList() << 13) // 13, shouldn't have incremented to 14.
 +            << QStringList()
 +            << QVariantList()
 +            << QStringList()
 +            << QVariantList();
 +
 +    QTest::newRow("qobject, writing + readonly constraints")
 +            << testFileUrl("moduleapi/qobjectModuleApiWriting.qml")
 +            << QString()
 +            << (QStringList() << QString(QLatin1String("file://") + testFileUrl("moduleapi/qobjectModuleApiWriting.qml").toLocalFile() + QLatin1String(":14: Error: Cannot assign to read-only property \"qobjectTestProperty\"")))
 +            << (QStringList() << "readOnlyProperty" << "writableProperty")
 +            << (QVariantList() << 20 << 50)
 +            << (QStringList() << "firstProperty" << "writableProperty")
 +            << (QVariantList() << 30 << 30)
 +            << (QStringList() << "readOnlyProperty" << "writableProperty")
 +            << (QVariantList() << 20 << 30);
 +
 +    QTest::newRow("script, writing + readonly constraints")
 +            << testFileUrl("moduleapi/scriptModuleApiWriting.qml")
 +            << QString()
 +            << (QStringList() << QString(QLatin1String("file://") + testFileUrl("moduleapi/scriptModuleApiWriting.qml").toLocalFile() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\"")))
 +            << (QStringList() << "readBack" << "unchanged")
 +            << (QVariantList() << 13 << 42)
 +            << (QStringList() << "firstProperty" << "secondProperty")
 +            << (QVariantList() << 30 << 30)
 +            << (QStringList() << "readBack" << "unchanged")
 +            << (QVariantList() << 30 << 42);
 +
 +    QTest::newRow("qobject module API enum values in JS")
 +            << testFileUrl("moduleapi/qobjectModuleApiEnums.qml")
 +            << QString()
 +            << QStringList()
 +            << (QStringList() << "enumValue" << "enumMethod")
 +            << (QVariantList() << 42 << 30)
 +            << QStringList()
 +            << QVariantList()
 +            << QStringList()
 +            << QVariantList();
 +
 +    QTest::newRow("qobject, invalid major version fail")
 +            << testFileUrl("moduleapi/moduleApiMajorVersionFail.qml")
 +            << QString("QQmlComponent: Component is not ready")
 +            << QStringList()
 +            << QStringList()
 +            << QVariantList()
 +            << QStringList()
 +            << QVariantList()
 +            << QStringList()
 +            << QVariantList();
 +
 +    QTest::newRow("qobject, invalid minor version fail")
 +            << testFileUrl("moduleapi/moduleApiMinorVersionFail.qml")
 +            << QString("QQmlComponent: Component is not ready")
 +            << QStringList()
 +            << QStringList()
 +            << QVariantList()
 +            << QStringList()
 +            << QVariantList()
 +            << QStringList()
 +            << QVariantList();
 +}
 +
 +void tst_qqmlecmascript::moduleApi()
 +{
 +    QFETCH(QUrl, testfile);
 +    QFETCH(QString, errorMessage);
 +    QFETCH(QStringList, warningMessages);
 +    QFETCH(QStringList, readProperties);
 +    QFETCH(QVariantList, readExpectedValues);
 +    QFETCH(QStringList, writeProperties);
 +    QFETCH(QVariantList, writeValues);
 +    QFETCH(QStringList, readBackProperties);
 +    QFETCH(QVariantList, readBackExpectedValues);
 +
 +    QQmlComponent component(&engine, testfile);
 +
 +    if (!errorMessage.isEmpty())
 +        QTest::ignoreMessage(QtWarningMsg, errorMessage.toAscii().constData());
 +
 +    if (warningMessages.size())
 +        foreach (const QString &warning, warningMessages)
 +            QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
 +
 +    QObject *object = component.create();
 +    if (!errorMessage.isEmpty()) {
 +        QVERIFY(object == 0);
 +    } else {
 +        QVERIFY(object != 0);
 +        for (int i = 0; i < readProperties.size(); ++i)
 +            QCOMPARE(object->property(readProperties.at(i).toAscii().constData()), readExpectedValues.at(i));
 +        for (int i = 0; i < writeProperties.size(); ++i)
 +            QVERIFY(object->setProperty(writeProperties.at(i).toAscii().constData(), writeValues.at(i)));
 +        for (int i = 0; i < readBackProperties.size(); ++i)
 +            QCOMPARE(object->property(readBackProperties.at(i).toAscii().constData()), readBackExpectedValues.at(i));
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::importScripts_data()
 +{
 +    QTest::addColumn<QUrl>("testfile");
 +    QTest::addColumn<QString>("errorMessage");
 +    QTest::addColumn<QStringList>("warningMessages");
 +    QTest::addColumn<QStringList>("propertyNames");
 +    QTest::addColumn<QVariantList>("propertyValues");
 +
 +    QTest::newRow("basic functionality")
 +            << testFileUrl("jsimport/testImport.qml")
 +            << QString()
 +            << QStringList()
 +            << (QStringList() << QLatin1String("importedScriptStringValue")
 +                              << QLatin1String("importedScriptFunctionValue")
 +                              << QLatin1String("importedModuleAttachedPropertyValue")
 +                              << QLatin1String("importedModuleEnumValue"))
 +            << (QVariantList() << QVariant(QLatin1String("Hello, World!"))
 +                               << QVariant(20)
 +                               << QVariant(19)
 +                               << QVariant(2));
 +
 +    QTest::newRow("import scoping")
 +            << testFileUrl("jsimport/testImportScoping.qml")
 +            << QString()
 +            << QStringList()
 +            << (QStringList() << QLatin1String("componentError"))
 +            << (QVariantList() << QVariant(5));
 +
 +    QTest::newRow("parent scope shouldn't be inherited by import with imports")
 +            << testFileUrl("jsimportfail/failOne.qml")
 +            << QString()
 +            << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined")))
 +            << (QStringList() << QLatin1String("importScriptFunctionValue"))
 +            << (QVariantList() << QVariant(QString()));
 +
 +    QTest::newRow("javascript imports in an import should be private to the import scope")
 +            << testFileUrl("jsimportfail/failTwo.qml")
 +            << QString()
 +            << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs")))
 +            << (QStringList() << QLatin1String("importScriptFunctionValue"))
 +            << (QVariantList() << QVariant(QString()));
 +
 +    QTest::newRow("module imports in an import should be private to the import scope")
 +            << testFileUrl("jsimportfail/failThree.qml")
 +            << QString()
 +            << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined")))
 +            << (QStringList() << QLatin1String("importedModuleAttachedPropertyValue"))
 +            << (QVariantList() << QVariant(false));
 +
 +    QTest::newRow("typenames in an import should be private to the import scope")
 +            << testFileUrl("jsimportfail/failFour.qml")
 +            << QString()
 +            << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest")))
 +            << (QStringList() << QLatin1String("importedModuleEnumValue"))
 +            << (QVariantList() << QVariant(0));
 +
 +    QTest::newRow("import with imports has it's own activation scope")
 +            << testFileUrl("jsimportfail/failFive.qml")
 +            << QString()
 +            << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component")))
 +            << (QStringList() << QLatin1String("componentError"))
 +            << (QVariantList() << QVariant(0));
 +
 +    QTest::newRow("import pragma library script")
 +            << testFileUrl("jsimport/testImportPragmaLibrary.qml")
 +            << QString()
 +            << QStringList()
 +            << (QStringList() << QLatin1String("testValue"))
 +            << (QVariantList() << QVariant(31));
 +
 +    QTest::newRow("pragma library imports shouldn't inherit parent imports or scope")
 +            << testFileUrl("jsimportfail/testImportPragmaLibrary.qml")
 +            << QString()
 +            << (QStringList() << QString(QLatin1String("file://") + testFileUrl("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component")))
 +            << (QStringList() << QLatin1String("testValue"))
 +            << (QVariantList() << QVariant(0));
 +
 +    QTest::newRow("import pragma library script which has an import")
 +            << testFileUrl("jsimport/testImportPragmaLibraryWithImports.qml")
 +            << QString()
 +            << QStringList()
 +            << (QStringList() << QLatin1String("testValue"))
 +            << (QVariantList() << QVariant(55));
 +
 +    QTest::newRow("import pragma library script which has a pragma library import")
 +            << testFileUrl("jsimport/testImportPragmaLibraryWithPragmaLibraryImports.qml")
 +            << QString()
 +            << QStringList()
 +            << (QStringList() << QLatin1String("testValue"))
 +            << (QVariantList() << QVariant(18));
++
++    QTest::newRow("import module api into js import")
++            << testFileUrl("jsimport/testImportModuleApi.qml")
++            << QString()
++            << QStringList()
++            << (QStringList() << QLatin1String("testValue"))
++            << (QVariantList() << QVariant(20));
 +}
 +
 +void tst_qqmlecmascript::importScripts()
 +{
 +    QFETCH(QUrl, testfile);
 +    QFETCH(QString, errorMessage);
 +    QFETCH(QStringList, warningMessages);
 +    QFETCH(QStringList, propertyNames);
 +    QFETCH(QVariantList, propertyValues);
 +
 +    QQmlComponent component(&engine, testfile);
 +
 +    if (!errorMessage.isEmpty())
 +        QTest::ignoreMessage(QtWarningMsg, errorMessage.toAscii().constData());
 +
 +    if (warningMessages.size())
 +        foreach (const QString &warning, warningMessages)
 +            QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
 +
 +    QObject *object = component.create();
 +    if (!errorMessage.isEmpty()) {
 +        QVERIFY(object == 0);
 +    } else {
 +        QVERIFY(object != 0);
 +        for (int i = 0; i < propertyNames.size(); ++i)
 +            QCOMPARE(object->property(propertyNames.at(i).toAscii().constData()), propertyValues.at(i));
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::scarceResources_other()
 +{
 +    /* These tests require knowledge of state, since we test values after
 +       performing signal or function invocation. */
 +
 +    QPixmap origPixmap(100, 100);
 +    origPixmap.fill(Qt::blue);
 +    QString srp_name, expectedWarning;
 +    QQmlEnginePrivate *ep = QQmlEnginePrivate::get(&engine);
 +    ScarceResourceObject *eo = 0;
 +    QObject *srsc = 0;
 +    QObject *object = 0;
 +
 +    /* property var semantics */
 +
 +    // test that scarce resources are handled properly in signal invocation
 +    QQmlComponent varComponentTen(&engine, testFileUrl("scarceResourceSignal.var.qml"));
 +    object = varComponentTen.create();
 +    srsc = object->findChild<QObject*>("srsc");
 +    QVERIFY(srsc);
 +    QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
 +    QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
 +    QMetaObject::invokeMethod(srsc, "testSignal");
 +    QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
 +    QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
 +    QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
 +    QVERIFY(srsc->property("scarceResourceCopy").isValid());
 +    QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
 +    QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
 +    delete object;
 +
 +    // test that scarce resources are handled properly from js functions in qml files
 +    QQmlComponent varComponentEleven(&engine, testFileUrl("scarceResourceFunction.var.qml"));
 +    object = varComponentEleven.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
 +    QMetaObject::invokeMethod(object, "retrieveScarceResource");
 +    QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
 +    QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
 +    QMetaObject::invokeMethod(object, "releaseScarceResource");
 +    QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
 +    QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
 +    delete object;
 +
 +    // test that if an exception occurs while invoking js function from cpp, that the resources are released.
 +    QQmlComponent varComponentTwelve(&engine, testFileUrl("scarceResourceFunctionFail.var.qml"));
 +    object = varComponentTwelve.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
 +    srp_name = object->property("srp_name").toString();
 +    expectedWarning = varComponentTwelve.url().toString() + QLatin1String(":16: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
 +    QMetaObject::invokeMethod(object, "retrieveScarceResource");
 +    QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
 +    QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
 +    delete object;
 +
 +    // test that if an Item which has JS ownership but has a scarce resource property is garbage collected,
 +    // that the scarce resource is removed from the engine's list of scarce resources to clean up.
 +    QQmlComponent varComponentThirteen(&engine, testFileUrl("scarceResourceObjectGc.var.qml"));
 +    object = varComponentThirteen.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(!object->property("varProperty").isValid()); // not assigned yet
 +    QMetaObject::invokeMethod(object, "assignVarProperty");
 +    QVERIFY(ep->scarceResources.isEmpty());             // the scarce resource is a VME property.
 +    QMetaObject::invokeMethod(object, "deassignVarProperty");
 +    QVERIFY(ep->scarceResources.isEmpty());             // should still be empty; the resource should have been released on gc.
 +    delete object;
 +
 +    /* property variant semantics */
 +
 +    // test that scarce resources are handled properly in signal invocation
 +    QQmlComponent variantComponentTen(&engine, testFileUrl("scarceResourceSignal.variant.qml"));
 +    object = variantComponentTen.create();
 +    QVERIFY(object != 0);
 +    srsc = object->findChild<QObject*>("srsc");
 +    QVERIFY(srsc);
 +    QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
 +    QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
 +    QMetaObject::invokeMethod(srsc, "testSignal");
 +    QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
 +    QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
 +    QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
 +    QVERIFY(srsc->property("scarceResourceCopy").isValid());
 +    QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
 +    QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
 +    delete object;
 +
 +    // test that scarce resources are handled properly from js functions in qml files
 +    QQmlComponent variantComponentEleven(&engine, testFileUrl("scarceResourceFunction.variant.qml"));
 +    object = variantComponentEleven.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
 +    QMetaObject::invokeMethod(object, "retrieveScarceResource");
 +    QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
 +    QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
 +    QMetaObject::invokeMethod(object, "releaseScarceResource");
 +    QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
 +    QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
 +    delete object;
 +
 +    // test that if an exception occurs while invoking js function from cpp, that the resources are released.
 +    QQmlComponent variantComponentTwelve(&engine, testFileUrl("scarceResourceFunctionFail.variant.qml"));
 +    object = variantComponentTwelve.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
 +    srp_name = object->property("srp_name").toString();
 +    expectedWarning = variantComponentTwelve.url().toString() + QLatin1String(":16: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
 +    QMetaObject::invokeMethod(object, "retrieveScarceResource");
 +    QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
 +    eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +    QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
 +    QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::scarceResources_data()
 +{
 +    QTest::addColumn<QUrl>("qmlFile");
 +    QTest::addColumn<bool>("readDetachStatus");
 +    QTest::addColumn<bool>("expectedDetachStatus");
 +    QTest::addColumn<QStringList>("propertyNames");
 +    QTest::addColumn<QVariantList>("expectedValidity");
 +    QTest::addColumn<QVariantList>("expectedValues");
 +    QTest::addColumn<QStringList>("expectedErrors");
 +
 +    QPixmap origPixmap(100, 100);
 +    origPixmap.fill(Qt::blue);
 +
 +    /* property var semantics */
 +
 +    // in the following three cases, the instance created from the component
 +    // has a property which is a copy of the scarce resource; hence, the
 +    // resource should NOT be detached prior to deletion of the object instance,
 +    // unless the resource is destroyed explicitly.
 +    QTest::newRow("var: import scarce resource copy directly")
 +        << testFileUrl("scarceResourceCopy.var.qml")
 +        << true
 +        << false // won't be detached, because assigned to property and not explicitly released
 +        << (QStringList() << QLatin1String("scarceResourceCopy"))
 +        << (QList<QVariant>() << true)
 +        << (QList<QVariant>() << origPixmap)
 +        << QStringList();
 +
 +    QTest::newRow("var: import scarce resource copy from JS")
 +        << testFileUrl("scarceResourceCopyFromJs.var.qml")
 +        << true
 +        << false // won't be detached, because assigned to property and not explicitly released
 +        << (QStringList() << QLatin1String("scarceResourceCopy"))
 +        << (QList<QVariant>() << true)
 +        << (QList<QVariant>() << origPixmap)
 +        << QStringList();
 +
 +    QTest::newRow("var: import released scarce resource copy from JS")
 +        << testFileUrl("scarceResourceDestroyedCopy.var.qml")
 +        << true
 +        << true // explicitly released, so it will be detached
 +        << (QStringList() << QLatin1String("scarceResourceCopy"))
 +        << (QList<QVariant>() << false)
 +        << (QList<QVariant>() << QVariant())
 +        << QStringList();
 +
 +    // in the following three cases, no other copy should exist in memory,
 +    // and so it should be detached (unless explicitly preserved).
 +    QTest::newRow("var: import auto-release SR from JS in binding side-effect")
 +        << testFileUrl("scarceResourceTest.var.qml")
 +        << true
 +        << true // auto released, so it will be detached
 +        << (QStringList() << QLatin1String("scarceResourceTest"))
 +        << (QList<QVariant>() << true)
 +        << (QList<QVariant>() << QVariant(100))
 +        << QStringList();
 +    QTest::newRow("var: import explicit-preserve SR from JS in binding side-effect")
 +        << testFileUrl("scarceResourceTestPreserve.var.qml")
 +        << true
 +        << false // won't be detached because we explicitly preserve it
 +        << (QStringList() << QLatin1String("scarceResourceTest"))
 +        << (QList<QVariant>() << true)
 +        << (QList<QVariant>() << QVariant(100))
 +        << QStringList();
 +    QTest::newRow("var: import explicit-preserve SR from JS in binding side-effect")
 +        << testFileUrl("scarceResourceTestMultiple.var.qml")
 +        << true
 +        << true // will be detached because all resources were released manually or automatically.
 +        << (QStringList() << QLatin1String("scarceResourceTest"))
 +        << (QList<QVariant>() << true)
 +        << (QList<QVariant>() << QVariant(100))
 +        << QStringList();
 +
 +    // In the following three cases, test that scarce resources are handled
 +    // correctly for imports.
 +    QTest::newRow("var: import with no binding")
 +        << testFileUrl("scarceResourceCopyImportNoBinding.var.qml")
 +        << false // cannot check detach status.
 +        << false
 +        << QStringList()
 +        << QList<QVariant>()
 +        << QList<QVariant>()
 +        << QStringList();
 +    QTest::newRow("var: import with binding without explicit preserve")
 +        << testFileUrl("scarceResourceCopyImportNoBinding.var.qml")
 +        << false
 +        << false
 +        << (QStringList() << QLatin1String("scarceResourceCopy"))
 +        << (QList<QVariant>() << false) // will have been released prior to evaluation of binding.
 +        << (QList<QVariant>() << QVariant())
 +        << QStringList();
 +    QTest::newRow("var: import with explicit release after binding evaluation")
 +        << testFileUrl("scarceResourceCopyImport.var.qml")
 +        << false
 +        << false
 +        << (QStringList() << QLatin1String("scarceResourceImportedCopy") << QLatin1String("scarceResourceAssignedCopyOne") << QLatin1String("scarceResourceAssignedCopyTwo") << QLatin1String("arePropertiesEqual"))
 +        << (QList<QVariant>() << false << false << false << true) // since property var = JS object reference, by releasing the provider's resource, all handles are invalidated.
 +        << (QList<QVariant>() << QVariant() << QVariant() << QVariant() << QVariant(true))
 +        << QStringList();
 +    QTest::newRow("var: import with different js objects")
 +        << testFileUrl("scarceResourceCopyImportDifferent.var.qml")
 +        << false
 +        << false
 +        << (QStringList() << QLatin1String("scarceResourceAssignedCopyOne") << QLatin1String("scarceResourceAssignedCopyTwo") << QLatin1String("arePropertiesEqual"))
 +        << (QList<QVariant>() << false << true << true) // invalidating one shouldn't invalidate the other, because they're not references to the same JS object.
 +        << (QList<QVariant>() << QVariant() << QVariant(origPixmap) << QVariant(false))
 +        << QStringList();
 +    QTest::newRow("var: import with different js objects and explicit release")
 +        << testFileUrl("scarceResourceMultipleDifferentNoBinding.var.qml")
 +        << false
 +        << false
 +        << (QStringList() << QLatin1String("resourceOne") << QLatin1String("resourceTwo"))
 +        << (QList<QVariant>() << true << false) // invalidating one shouldn't invalidate the other, because they're not references to the same JS object.
 +        << (QList<QVariant>() << QVariant(origPixmap) << QVariant())
 +        << QStringList();
 +    QTest::newRow("var: import with same js objects and explicit release")
 +        << testFileUrl("scarceResourceMultipleSameNoBinding.var.qml")
 +        << false
 +        << false
 +        << (QStringList() << QLatin1String("resourceOne") << QLatin1String("resourceTwo"))
 +        << (QList<QVariant>() << false << false) // invalidating one should invalidate the other, because they're references to the same JS object.
 +        << (QList<QVariant>() << QVariant() << QVariant())
 +        << QStringList();
 +    QTest::newRow("var: binding with same js objects and explicit release")
 +        << testFileUrl("scarceResourceMultipleSameWithBinding.var.qml")
 +        << false
 +        << false
 +        << (QStringList() << QLatin1String("resourceOne") << QLatin1String("resourceTwo"))
 +        << (QList<QVariant>() << false << false) // invalidating one should invalidate the other, because they're references to the same JS object.
 +        << (QList<QVariant>() << QVariant() << QVariant())
 +        << QStringList();
 +
 +
 +    /* property variant semantics */
 +
 +    // in the following three cases, the instance created from the component
 +    // has a property which is a copy of the scarce resource; hence, the
 +    // resource should NOT be detached prior to deletion of the object instance,
 +    // unless the resource is destroyed explicitly.
 +    QTest::newRow("variant: import scarce resource copy directly")
 +        << testFileUrl("scarceResourceCopy.variant.qml")
 +        << true
 +        << false // won't be detached, because assigned to property and not explicitly released
 +        << (QStringList() << QLatin1String("scarceResourceCopy"))
 +        << (QList<QVariant>() << true)
 +        << (QList<QVariant>() << origPixmap)
 +        << QStringList();
 +
 +    QTest::newRow("variant: import scarce resource copy from JS")
 +        << testFileUrl("scarceResourceCopyFromJs.variant.qml")
 +        << true
 +        << false // won't be detached, because assigned to property and not explicitly released
 +        << (QStringList() << QLatin1String("scarceResourceCopy"))
 +        << (QList<QVariant>() << true)
 +        << (QList<QVariant>() << origPixmap)
 +        << QStringList();
 +
 +    QTest::newRow("variant: import released scarce resource copy from JS")
 +        << testFileUrl("scarceResourceDestroyedCopy.variant.qml")
 +        << true
 +        << true // explicitly released, so it will be detached
 +        << (QStringList() << QLatin1String("scarceResourceCopy"))
 +        << (QList<QVariant>() << false)
 +        << (QList<QVariant>() << QVariant())
 +        << QStringList();
 +
 +    // in the following three cases, no other copy should exist in memory,
 +    // and so it should be detached (unless explicitly preserved).
 +    QTest::newRow("variant: import auto-release SR from JS in binding side-effect")
 +        << testFileUrl("scarceResourceTest.variant.qml")
 +        << true
 +        << true // auto released, so it will be detached
 +        << (QStringList() << QLatin1String("scarceResourceTest"))
 +        << (QList<QVariant>() << true)
 +        << (QList<QVariant>() << QVariant(100))
 +        << QStringList();
 +    QTest::newRow("variant: import explicit-preserve SR from JS in binding side-effect")
 +        << testFileUrl("scarceResourceTestPreserve.variant.qml")
 +        << true
 +        << false // won't be detached because we explicitly preserve it
 +        << (QStringList() << QLatin1String("scarceResourceTest"))
 +        << (QList<QVariant>() << true)
 +        << (QList<QVariant>() << QVariant(100))
 +        << QStringList();
 +    QTest::newRow("variant: import multiple scarce resources")
 +        << testFileUrl("scarceResourceTestMultiple.variant.qml")
 +        << true
 +        << true // will be detached because all resources were released manually or automatically.
 +        << (QStringList() << QLatin1String("scarceResourceTest"))
 +        << (QList<QVariant>() << true)
 +        << (QList<QVariant>() << QVariant(100))
 +        << QStringList();
 +
 +    // In the following three cases, test that scarce resources are handled
 +    // correctly for imports.
 +    QTest::newRow("variant: import with no binding")
 +        << testFileUrl("scarceResourceCopyImportNoBinding.variant.qml")
 +        << false // cannot check detach status.
 +        << false
 +        << QStringList()
 +        << QList<QVariant>()
 +        << QList<QVariant>()
 +        << QStringList();
 +    QTest::newRow("variant: import with binding without explicit preserve")
 +        << testFileUrl("scarceResourceCopyImportNoBinding.variant.qml")
 +        << false
 +        << false
 +        << (QStringList() << QLatin1String("scarceResourceCopy"))
 +        << (QList<QVariant>() << false) // will have been released prior to evaluation of binding.
 +        << (QList<QVariant>() << QVariant())
 +        << QStringList();
 +    QTest::newRow("variant: import with explicit release after binding evaluation")
 +        << testFileUrl("scarceResourceCopyImport.variant.qml")
 +        << false
 +        << false
 +        << (QStringList() << QLatin1String("scarceResourceImportedCopy") << QLatin1String("scarceResourceAssignedCopyOne") << QLatin1String("scarceResourceAssignedCopyTwo"))
 +        << (QList<QVariant>() << true << true << false) // since property variant = variant copy, releasing the provider's resource does not invalidate previously assigned copies.
 +        << (QList<QVariant>() << origPixmap << origPixmap << QVariant())
 +        << QStringList();
 +}
 +
 +void tst_qqmlecmascript::scarceResources()
 +{
 +    QFETCH(QUrl, qmlFile);
 +    QFETCH(bool, readDetachStatus);
 +    QFETCH(bool, expectedDetachStatus);
 +    QFETCH(QStringList, propertyNames);
 +    QFETCH(QVariantList, expectedValidity);
 +    QFETCH(QVariantList, expectedValues);
 +    QFETCH(QStringList, expectedErrors);
 +
 +    QQmlEnginePrivate *ep = QQmlEnginePrivate::get(&engine);
 +    ScarceResourceObject *eo = 0;
 +    QObject *object = 0;
 +
 +    QQmlComponent c(&engine, qmlFile);
 +    object = c.create();
 +    QVERIFY(object != 0);
 +    for (int i = 0; i < propertyNames.size(); ++i) {
 +        QString prop = propertyNames.at(i);
 +        bool validity = expectedValidity.at(i).toBool();
 +        QVariant value = expectedValues.at(i);
 +
 +        QCOMPARE(object->property(prop.toLatin1().constData()).isValid(), validity);
 +        if (value.type() == QVariant::Int) {
 +            QCOMPARE(object->property(prop.toLatin1().constData()).toInt(), value.toInt());
 +        } else if (value.type() == QVariant::Pixmap) {
 +            QCOMPARE(object->property(prop.toLatin1().constData()).value<QPixmap>(), value.value<QPixmap>());
 +        }
 +    }
 +
 +    if (readDetachStatus) {
 +        eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
 +        QCOMPARE(eo->scarceResourceIsDetached(), expectedDetachStatus);
 +    }
 +
 +    QVERIFY(ep->scarceResources.isEmpty());
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::propertyChangeSlots()
 +{
 +    // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
 +    QQmlComponent component(&engine, testFileUrl("changeslots/propertyChangeSlots.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    delete object;
 +
 +    // ensure that invalid property names fail properly.
 +    QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
 +    QQmlComponent e1(&engine, testFileUrl("changeslots/propertyChangeSlotErrors.1.qml"));
 +    QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
 +    QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
 +    object = e1.create();
 +    QVERIFY(object == 0);
 +    delete object;
 +
 +    QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
 +    QQmlComponent e2(&engine, testFileUrl("changeslots/propertyChangeSlotErrors.2.qml"));
 +    expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
 +    QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
 +    object = e2.create();
 +    QVERIFY(object == 0);
 +    delete object;
 +
 +    QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
 +    QQmlComponent e3(&engine, testFileUrl("changeslots/propertyChangeSlotErrors.3.qml"));
 +    expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
 +    QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
 +    object = e3.create();
 +    QVERIFY(object == 0);
 +    delete object;
 +
 +    QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
 +    QQmlComponent e4(&engine, testFileUrl("changeslots/propertyChangeSlotErrors.4.qml"));
 +    expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
 +    QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
 +    object = e4.create();
 +    QVERIFY(object == 0);
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::propertyVar_data()
 +{
 +    QTest::addColumn<QUrl>("qmlFile");
 +
 +    // valid
 +    QTest::newRow("non-bindable object subproperty changed") << testFileUrl("propertyVar.1.qml");
 +    QTest::newRow("non-bindable object changed") << testFileUrl("propertyVar.2.qml");
 +    QTest::newRow("primitive changed") << testFileUrl("propertyVar.3.qml");
 +    QTest::newRow("javascript array modification") << testFileUrl("propertyVar.4.qml");
 +    QTest::newRow("javascript map modification") << testFileUrl("propertyVar.5.qml");
 +    QTest::newRow("javascript array assignment") << testFileUrl("propertyVar.6.qml");
 +    QTest::newRow("javascript map assignment") << testFileUrl("propertyVar.7.qml");
 +    QTest::newRow("literal property assignment") << testFileUrl("propertyVar.8.qml");
 +    QTest::newRow("qobject property assignment") << testFileUrl("propertyVar.9.qml");
 +    QTest::newRow("base class var property assignment") << testFileUrl("propertyVar.10.qml");
 +}
 +
 +void tst_qqmlecmascript::propertyVar()
 +{
 +    QFETCH(QUrl, qmlFile);
 +
 +    QQmlComponent component(&engine, qmlFile);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +}
 +
 +// Tests that we can write QVariant values to var properties from C++
 +void tst_qqmlecmascript::propertyVarCpp()
 +{
 +    QObject *object = 0;
 +
 +    // ensure that writing to and reading from a var property from cpp works as required.
 +    // Literal values stored in var properties can be read and written as QVariants
 +    // of a specific type, whereas object values are read as QVariantMaps.
 +    QQmlComponent component(&engine, testFileUrl("propertyVarCpp.qml"));
 +    object = component.create();
 +    QVERIFY(object != 0);
 +    // assign int to property var that currently has int assigned
 +    QVERIFY(object->setProperty("varProperty", QVariant::fromValue(10)));
 +    QCOMPARE(object->property("varBound"), QVariant(15));
 +    QCOMPARE(object->property("intBound"), QVariant(15));
 +    QCOMPARE(object->property("varProperty").userType(), (int)QVariant::Int);
 +    QCOMPARE(object->property("varBound").userType(), (int)QVariant::Int);
 +    // assign string to property var that current has bool assigned
 +    QCOMPARE(object->property("varProperty2").userType(), (int)QVariant::Bool);
 +    QVERIFY(object->setProperty("varProperty2", QVariant(QLatin1String("randomString"))));
 +    QCOMPARE(object->property("varProperty2"), QVariant(QLatin1String("randomString")));
 +    QCOMPARE(object->property("varProperty2").userType(), (int)QVariant::String);
 +    // now enforce behaviour when accessing JavaScript objects from cpp.
 +    QCOMPARE(object->property("jsobject").userType(), (int)QVariant::Map);
 +    delete object;
 +}
 +
 +static void gc(QQmlEngine &engine)
 +{
 +    engine.collectGarbage();
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +    QCoreApplication::processEvents();
 +}
 +
 +void tst_qqmlecmascript::propertyVarOwnership()
 +{
 +    // Referenced JS objects are not collected
 +    {
 +    QQmlComponent component(&engine, testFileUrl("propertyVarOwnership.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->property("test").toBool(), false);
 +    QMetaObject::invokeMethod(object, "runTest");
 +    QCOMPARE(object->property("test").toBool(), true);
 +    delete object;
 +    }
 +    // Referenced JS objects are not collected
 +    {
 +    QQmlComponent component(&engine, testFileUrl("propertyVarOwnership.2.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->property("test").toBool(), false);
 +    QMetaObject::invokeMethod(object, "runTest");
 +    QCOMPARE(object->property("test").toBool(), true);
 +    delete object;
 +    }
 +    // Qt objects are not collected until they've been dereferenced
 +    {
 +    QQmlComponent component(&engine, testFileUrl("propertyVarOwnership.3.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test2").toBool(), false);
 +    QCOMPARE(object->property("test2").toBool(), false);
 +
 +    QMetaObject::invokeMethod(object, "runTest");
 +    QCOMPARE(object->property("test1").toBool(), true);
 +
 +    QPointer<QObject> referencedObject = object->property("object").value<QObject*>();
 +    QVERIFY(!referencedObject.isNull());
 +    gc(engine);
 +    QVERIFY(!referencedObject.isNull());
 +
 +    QMetaObject::invokeMethod(object, "runTest2");
 +    QCOMPARE(object->property("test2").toBool(), true);
 +    gc(engine);
 +    QVERIFY(referencedObject.isNull());
 +
 +    delete object;
 +    }
 +    // Self reference does not prevent Qt object collection
 +    {
 +    QQmlComponent component(&engine, testFileUrl("propertyVarOwnership.4.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    QPointer<QObject> referencedObject = object->property("object").value<QObject*>();
 +    QVERIFY(!referencedObject.isNull());
 +    gc(engine);
 +    QVERIFY(!referencedObject.isNull());
 +
 +    QMetaObject::invokeMethod(object, "runTest");
 +    gc(engine);
 +    QVERIFY(referencedObject.isNull());
 +
 +    delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::propertyVarImplicitOwnership()
 +{
 +    // The childObject has a reference to a different QObject.  We want to ensure
 +    // that the different item will not be cleaned up until required.  IE, the childObject
 +    // has implicit ownership of the constructed QObject.
 +    QQmlComponent component(&engine, testFileUrl("propertyVarImplicitOwnership.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "assignCircular");
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QObject *rootObject = object->property("vp").value<QObject*>();
 +    QVERIFY(rootObject != 0);
 +    QObject *childObject = rootObject->findChild<QObject*>("text");
 +    QVERIFY(childObject != 0);
 +    QCOMPARE(rootObject->property("rectCanary").toInt(), 5);
 +    QCOMPARE(childObject->property("textCanary").toInt(), 10);
 +    QMetaObject::invokeMethod(childObject, "constructQObject");    // creates a reference to a constructed QObject.
 +    QWeakPointer<QObject> qobjectGuard(childObject->property("vp").value<QObject*>()); // get the pointer prior to processing deleteLater events.
 +    QVERIFY(!qobjectGuard.isNull());
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QVERIFY(!qobjectGuard.isNull());
 +    QMetaObject::invokeMethod(object, "deassignCircular");
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QVERIFY(qobjectGuard.isNull());                                // should have been collected now.
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::propertyVarReparent()
 +{
 +    // ensure that nothing breaks if we re-parent objects
 +    QQmlComponent component(&engine, testFileUrl("propertyVar.reparent.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "assignVarProp");
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QObject *rect = object->property("vp").value<QObject*>();
 +    QObject *text = rect->findChild<QObject*>("textOne");
 +    QObject *text2 = rect->findChild<QObject*>("textTwo");
 +    QWeakPointer<QObject> rectGuard(rect);
 +    QWeakPointer<QObject> textGuard(text);
 +    QWeakPointer<QObject> text2Guard(text2);
 +    QVERIFY(!rectGuard.isNull());
 +    QVERIFY(!textGuard.isNull());
 +    QVERIFY(!text2Guard.isNull());
 +    QCOMPARE(text->property("textCanary").toInt(), 11);
 +    QCOMPARE(text2->property("textCanary").toInt(), 12);
 +    // now construct an image which we will reparent.
 +    QMetaObject::invokeMethod(text2, "constructQObject");
 +    QObject *image = text2->property("vp").value<QObject*>();
 +    QWeakPointer<QObject> imageGuard(image);
 +    QVERIFY(!imageGuard.isNull());
 +    QCOMPARE(image->property("imageCanary").toInt(), 13);
 +    // now reparent the "Image" object (currently, it has JS ownership)
 +    image->setParent(text);                                        // shouldn't be collected after deassignVp now, since has a parent.
 +    QMetaObject::invokeMethod(text2, "deassignVp");
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QCOMPARE(text->property("textCanary").toInt(), 11);
 +    QCOMPARE(text2->property("textCanary").toInt(), 22);
 +    QVERIFY(!imageGuard.isNull());                                 // should still be alive.
 +    QCOMPARE(image->property("imageCanary").toInt(), 13);          // still able to access var properties
 +    QMetaObject::invokeMethod(object, "deassignVarProp");          // now deassign the root-object's vp, causing gc of rect+text+text2
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QVERIFY(imageGuard.isNull());                                  // should now have been deleted, due to parent being deleted.
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::propertyVarReparentNullContext()
 +{
 +    // sometimes reparenting can cause problems
 +    // (eg, if the ctxt is collected, varproperties are no longer available)
 +    // this test ensures that no crash occurs in that situation.
 +    QQmlComponent component(&engine, testFileUrl("propertyVar.reparent.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "assignVarProp");
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QObject *rect = object->property("vp").value<QObject*>();
 +    QObject *text = rect->findChild<QObject*>("textOne");
 +    QObject *text2 = rect->findChild<QObject*>("textTwo");
 +    QWeakPointer<QObject> rectGuard(rect);
 +    QWeakPointer<QObject> textGuard(text);
 +    QWeakPointer<QObject> text2Guard(text2);
 +    QVERIFY(!rectGuard.isNull());
 +    QVERIFY(!textGuard.isNull());
 +    QVERIFY(!text2Guard.isNull());
 +    QCOMPARE(text->property("textCanary").toInt(), 11);
 +    QCOMPARE(text2->property("textCanary").toInt(), 12);
 +    // now construct an image which we will reparent.
 +    QMetaObject::invokeMethod(text2, "constructQObject");
 +    QObject *image = text2->property("vp").value<QObject*>();
 +    QWeakPointer<QObject> imageGuard(image);
 +    QVERIFY(!imageGuard.isNull());
 +    QCOMPARE(image->property("imageCanary").toInt(), 13);
 +    // now reparent the "Image" object (currently, it has JS ownership)
 +    image->setParent(object);                                      // reparented to base object.  after deassignVarProp, the ctxt will be invalid.
 +    QMetaObject::invokeMethod(object, "deassignVarProp");          // now deassign the root-object's vp, causing gc of rect+text+text2
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QVERIFY(!imageGuard.isNull());                                 // should still be alive.
 +    QVERIFY(!image->property("imageCanary").isValid());            // but varProperties won't be available (null context).
 +    delete object;
 +    QVERIFY(imageGuard.isNull());                                  // should now be dead.
 +}
 +
 +void tst_qqmlecmascript::propertyVarCircular()
 +{
 +    // enforce behaviour regarding circular references - ensure qdvmemo deletion.
 +    QQmlComponent component(&engine, testFileUrl("propertyVar.circular.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "assignCircular");           // cause assignment and gc
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QCOMPARE(object->property("canaryInt"), QVariant(5));
 +    QVariant canaryResourceVariant = object->property("canaryResource");
 +    QVERIFY(canaryResourceVariant.isValid());
 +    QPixmap canaryResourcePixmap = canaryResourceVariant.value<QPixmap>();
 +    canaryResourceVariant = QVariant();                            // invalidate it to remove one copy of the pixmap from memory.
 +    QMetaObject::invokeMethod(object, "deassignCanaryResource");   // remove one copy of the pixmap from memory
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QVERIFY(!canaryResourcePixmap.isDetached());                   // two copies extant - this and the propertyVar.vp.vp.vp.vp.memoryHog.
 +    QMetaObject::invokeMethod(object, "deassignCircular");         // cause deassignment and gc
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QCOMPARE(object->property("canaryInt"), QVariant(2));
 +    QCOMPARE(object->property("canaryResource"), QVariant(1));
 +    QVERIFY(canaryResourcePixmap.isDetached());                    // now detached, since orig copy was member of qdvmemo which was deleted.
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::propertyVarCircular2()
 +{
 +    // track deletion of JS-owned parent item with Cpp-owned child
 +    // where the child has a var property referencing its parent.
 +    QQmlComponent component(&engine, testFileUrl("propertyVar.circular.2.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "assignCircular");
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QObject *rootObject = object->property("vp").value<QObject*>();
 +    QVERIFY(rootObject != 0);
 +    QObject *childObject = rootObject->findChild<QObject*>("text");
 +    QVERIFY(childObject != 0);
 +    QWeakPointer<QObject> rootObjectTracker(rootObject);
 +    QVERIFY(!rootObjectTracker.isNull());
 +    QWeakPointer<QObject> childObjectTracker(childObject);
 +    QVERIFY(!childObjectTracker.isNull());
 +    gc(engine);
 +    QCOMPARE(rootObject->property("rectCanary").toInt(), 5);
 +    QCOMPARE(childObject->property("textCanary").toInt(), 10);
 +    QMetaObject::invokeMethod(object, "deassignCircular");
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QVERIFY(rootObjectTracker.isNull());                           // should have been collected
 +    QVERIFY(childObjectTracker.isNull());                          // should have been collected
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter)
 +{
 +    *(int*)(parameter) += 1;
 +    qPersistentDispose(object);
 +}
 +
 +void tst_qqmlecmascript::propertyVarInheritance()
 +{
 +    int propertyVarWeakRefCallbackCount = 0;
 +
 +    // enforce behaviour regarding element inheritance - ensure handle disposal.
 +    // The particular component under test here has a chain of references.
 +    QQmlComponent component(&engine, testFileUrl("propertyVar.inherit.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "assignCircular");           // cause assignment and gc
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    // we want to be able to track when the varProperties array of the last metaobject is disposed
 +    QObject *cco5 = object->property("varProperty").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>();
 +    QObject *ico5 = object->property("varProperty").value<QObject*>()->property("inheritanceVarProperty").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>()->property("vp").value<QObject*>();
 +    QQmlVMEMetaObject *icovmemo = ((QQmlVMEMetaObject *)(ico5->metaObject()));
 +    QQmlVMEMetaObject *ccovmemo = ((QQmlVMEMetaObject *)(cco5->metaObject()));
 +    v8::Persistent<v8::Value> icoCanaryHandle;
 +    v8::Persistent<v8::Value> ccoCanaryHandle;
 +    {
 +        v8::HandleScope hs;
 +        // XXX NOTE: this is very implementation dependent.  QDVMEMO->vmeProperty() is the only
 +        // public function which can return us a handle to something in the varProperties array.
 +        icoCanaryHandle = qPersistentNew(icovmemo->vmeProperty(ico5->metaObject()->indexOfProperty("circ")));
 +        ccoCanaryHandle = qPersistentNew(ccovmemo->vmeProperty(cco5->metaObject()->indexOfProperty("circ")));
 +        // we make them weak and invoke the gc, but we should not hit the weak-callback yet
 +        // as the varproperties array of each vmemo still references the resource.
 +        icoCanaryHandle.MakeWeak(&propertyVarWeakRefCallbackCount, propertyVarWeakRefCallback);
 +        ccoCanaryHandle.MakeWeak(&propertyVarWeakRefCallbackCount, propertyVarWeakRefCallback);
 +        gc(engine);
 +        QVERIFY(propertyVarWeakRefCallbackCount == 0);
 +    }
 +    // now we deassign the var prop, which should trigger collection of item subtrees.
 +    QMetaObject::invokeMethod(object, "deassignCircular");         // cause deassignment and gc
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    // ensure that there are only weak handles to the underlying varProperties array remaining.
 +    gc(engine);
 +    QCOMPARE(propertyVarWeakRefCallbackCount, 2);                  // should have been called for both, since all refs should be weak.
 +    delete object;
 +    // since there are no parent vmemo's to keep implicit references alive, and the only handles
 +    // to what remains are weak, all varProperties arrays must have been collected.
 +}
 +
 +void tst_qqmlecmascript::propertyVarInheritance2()
 +{
 +    int propertyVarWeakRefCallbackCount = 0;
 +
 +    // The particular component under test here does NOT have a chain of references; the
 +    // only link between rootObject and childObject is that rootObject is the parent of childObject.
 +    QQmlComponent component(&engine, testFileUrl("propertyVar.circular.2.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "assignCircular");
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QObject *rootObject = object->property("vp").value<QObject*>();
 +    QVERIFY(rootObject != 0);
 +    QObject *childObject = rootObject->findChild<QObject*>("text");
 +    QVERIFY(childObject != 0);
 +    QCOMPARE(rootObject->property("rectCanary").toInt(), 5);
 +    QCOMPARE(childObject->property("textCanary").toInt(), 10);
 +    v8::Persistent<v8::Value> childObjectVarArrayValueHandle;
 +    {
 +        v8::HandleScope hs;
 +        propertyVarWeakRefCallbackCount = 0;                           // reset callback count.
 +        childObjectVarArrayValueHandle = qPersistentNew(((QQmlVMEMetaObject *)(childObject->metaObject()))->vmeProperty(childObject->metaObject()->indexOfProperty("vp")));
 +        childObjectVarArrayValueHandle.MakeWeak(&propertyVarWeakRefCallbackCount, propertyVarWeakRefCallback);
 +        gc(engine);
 +        QVERIFY(propertyVarWeakRefCallbackCount == 0);                 // should not have been collected yet.
 +        QCOMPARE(childObject->property("vp").value<QObject*>(), rootObject);
 +        QCOMPARE(childObject->property("textCanary").toInt(), 10);
 +    }
 +    QMetaObject::invokeMethod(object, "deassignCircular");
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
 +    QCoreApplication::processEvents();
 +    QVERIFY(propertyVarWeakRefCallbackCount == 1);                 // should have been collected now.
 +    delete object;
 +}
 +
 +// Ensure that QObject type conversion works on binding assignment
 +void tst_qqmlecmascript::elementAssign()
 +{
 +    QQmlComponent component(&engine, testFileUrl("elementAssign.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +}
 +
 +// QTBUG-12457
 +void tst_qqmlecmascript::objectPassThroughSignals()
 +{
 +    QQmlComponent component(&engine, testFileUrl("objectsPassThroughSignals.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +}
 +
 +// QTBUG-21626
 +void tst_qqmlecmascript::objectConversion()
 +{
 +    QQmlComponent component(&engine, testFileUrl("objectConversion.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QVariant retn;
 +    QMetaObject::invokeMethod(object, "circularObject", Q_RETURN_ARG(QVariant, retn));
 +    QCOMPARE(retn.value<QVariantMap>().value("test"), QVariant(100));
 +
 +    delete object;
 +}
 +
 +
 +// QTBUG-20242
 +void tst_qqmlecmascript::booleanConversion()
 +{
 +    QQmlComponent component(&engine, testFileUrl("booleanConversion.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test_true1").toBool(), true);
 +    QCOMPARE(object->property("test_true2").toBool(), true);
 +    QCOMPARE(object->property("test_true3").toBool(), true);
 +    QCOMPARE(object->property("test_true4").toBool(), true);
 +    QCOMPARE(object->property("test_true5").toBool(), true);
 +
 +    QCOMPARE(object->property("test_false1").toBool(), false);
 +    QCOMPARE(object->property("test_false2").toBool(), false);
 +    QCOMPARE(object->property("test_false3").toBool(), false);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::handleReferenceManagement()
 +{
 +
 +    int dtorCount = 0;
 +    {
 +        // Linear QObject reference
 +        QQmlEngine hrmEngine;
 +        QQmlComponent component(&hrmEngine, testFileUrl("handleReferenceManagement.object.1.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        CircularReferenceObject *cro = object->findChild<CircularReferenceObject*>("cro");
 +        cro->setEngine(&hrmEngine);
 +        cro->setDtorCount(&dtorCount);
 +        QMetaObject::invokeMethod(object, "createReference");
 +        gc(engine);
 +        QCOMPARE(dtorCount, 0); // second has JS ownership, kept alive by first's reference
 +        delete object;
 +        hrmEngine.collectGarbage();
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +        QCOMPARE(dtorCount, 3);
 +    }
 +
 +    dtorCount = 0;
 +    {
 +        // Circular QObject reference
 +        QQmlEngine hrmEngine;
 +        QQmlComponent component(&hrmEngine, testFileUrl("handleReferenceManagement.object.2.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        CircularReferenceObject *cro = object->findChild<CircularReferenceObject*>("cro");
 +        cro->setEngine(&hrmEngine);
 +        cro->setDtorCount(&dtorCount);
 +        QMetaObject::invokeMethod(object, "circularReference");
 +        gc(engine);
 +        QCOMPARE(dtorCount, 2); // both should be cleaned up, since circular references shouldn't keep alive.
 +        delete object;
 +        hrmEngine.collectGarbage();
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +        QCOMPARE(dtorCount, 3);
 +    }
 +
 +    dtorCount = 0;
 +    {
 +        // Linear handle reference
 +        QQmlEngine hrmEngine;
 +        QQmlComponent component(&hrmEngine, testFileUrl("handleReferenceManagement.handle.1.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        CircularReferenceHandle *crh = object->findChild<CircularReferenceHandle*>("crh");
 +        QVERIFY(crh != 0);
 +        crh->setEngine(&hrmEngine);
 +        crh->setDtorCount(&dtorCount);
 +        QMetaObject::invokeMethod(object, "createReference");
 +        CircularReferenceHandle *first = object->property("first").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *second = object->property("second").value<CircularReferenceHandle*>();
 +        QVERIFY(first != 0);
 +        QVERIFY(second != 0);
 +        first->addReference(QQmlData::get(second)->v8object); // create reference
 +        // now we have to reparent second and make second owned by JS.
 +        second->setParent(0);
 +        QQmlEngine::setObjectOwnership(second, QQmlEngine::JavaScriptOwnership);
 +        gc(engine);
 +        QCOMPARE(dtorCount, 0); // due to reference from first to second, second shouldn't be collected.
 +        delete object;
 +        hrmEngine.collectGarbage();
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +        QCOMPARE(dtorCount, 3);
 +    }
 +
 +    dtorCount = 0;
 +    {
 +        // Circular handle reference
 +        QQmlEngine hrmEngine;
 +        QQmlComponent component(&hrmEngine, testFileUrl("handleReferenceManagement.handle.2.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        CircularReferenceHandle *crh = object->findChild<CircularReferenceHandle*>("crh");
 +        QVERIFY(crh != 0);
 +        crh->setEngine(&hrmEngine);
 +        crh->setDtorCount(&dtorCount);
 +        QMetaObject::invokeMethod(object, "circularReference");
 +        CircularReferenceHandle *first = object->property("first").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *second = object->property("second").value<CircularReferenceHandle*>();
 +        QVERIFY(first != 0);
 +        QVERIFY(second != 0);
 +        first->addReference(QQmlData::get(second)->v8object); // create circular reference
 +        second->addReference(QQmlData::get(first)->v8object); // note: must be weak.
 +        // now we have to reparent and change ownership.
 +        first->setParent(0);
 +        second->setParent(0);
 +        QQmlEngine::setObjectOwnership(first, QQmlEngine::JavaScriptOwnership);
 +        QQmlEngine::setObjectOwnership(second, QQmlEngine::JavaScriptOwnership);
 +        gc(engine);
 +        QCOMPARE(dtorCount, 2); // despite circular references, both will be collected.
 +        delete object;
 +        hrmEngine.collectGarbage();
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +        QCOMPARE(dtorCount, 3);
 +    }
 +
 +    dtorCount = 0;
 +    {
 +        // multiple engine interaction - linear reference
 +        QQmlEngine hrmEngine1;
 +        QQmlEngine hrmEngine2;
 +        QQmlComponent component1(&hrmEngine1, testFileUrl("handleReferenceManagement.handle.1.qml"));
 +        QQmlComponent component2(&hrmEngine2, testFileUrl("handleReferenceManagement.handle.1.qml"));
 +        QObject *object1 = component1.create();
 +        QObject *object2 = component2.create();
 +        QVERIFY(object1 != 0);
 +        QVERIFY(object2 != 0);
 +        CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
 +        CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
 +        QVERIFY(crh1 != 0);
 +        QVERIFY(crh2 != 0);
 +        crh1->setEngine(&hrmEngine1);
 +        crh2->setEngine(&hrmEngine2);
 +        crh1->setDtorCount(&dtorCount);
 +        crh2->setDtorCount(&dtorCount);
 +        QMetaObject::invokeMethod(object1, "createReference");
 +        QMetaObject::invokeMethod(object2, "createReference");
 +        CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
 +        QVERIFY(first1 != 0);
 +        QVERIFY(second1 != 0);
 +        QVERIFY(first2 != 0);
 +        QVERIFY(second2 != 0);
 +        first1->addReference(QQmlData::get(second2)->v8object); // create reference across engines
 +        // now we have to reparent second2 and make second2 owned by JS.
 +        second2->setParent(0);
 +        QQmlEngine::setObjectOwnership(second2, QQmlEngine::JavaScriptOwnership);
 +        gc(engine);
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +        QCOMPARE(dtorCount, 0); // due to reference from first1 to second2, second2 shouldn't be collected.
 +        delete object1;
 +        delete object2;
 +        hrmEngine1.collectGarbage();
 +        hrmEngine2.collectGarbage();
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +        QCOMPARE(dtorCount, 6);
 +    }
 +
 +    dtorCount = 0;
 +    {
 +        // multiple engine interaction - circular reference
 +        QQmlEngine hrmEngine1;
 +        QQmlEngine hrmEngine2;
 +        QQmlComponent component1(&hrmEngine1, testFileUrl("handleReferenceManagement.handle.1.qml"));
 +        QQmlComponent component2(&hrmEngine2, testFileUrl("handleReferenceManagement.handle.1.qml"));
 +        QObject *object1 = component1.create();
 +        QObject *object2 = component2.create();
 +        QVERIFY(object1 != 0);
 +        QVERIFY(object2 != 0);
 +        CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
 +        CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
 +        QVERIFY(crh1 != 0);
 +        QVERIFY(crh2 != 0);
 +        crh1->setEngine(&hrmEngine1);
 +        crh2->setEngine(&hrmEngine2);
 +        crh1->setDtorCount(&dtorCount);
 +        crh2->setDtorCount(&dtorCount);
 +        QMetaObject::invokeMethod(object1, "createReference");
 +        QMetaObject::invokeMethod(object2, "createReference");
 +        CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
 +        QVERIFY(first1 != 0);
 +        QVERIFY(second1 != 0);
 +        QVERIFY(first2 != 0);
 +        QVERIFY(second2 != 0);
 +        first1->addReference(QQmlData::get(second1)->v8object);  // create linear reference within engine1
 +        second1->addReference(QQmlData::get(second2)->v8object); // create linear reference across engines
 +        second2->addReference(QQmlData::get(first2)->v8object);  // create linear reference within engine2
 +        first2->addReference(QQmlData::get(first1)->v8object);   // close the loop - circular ref across engines
 +        // now we have to reparent and change ownership to JS.
 +        first1->setParent(0);
 +        second1->setParent(0);
 +        first2->setParent(0);
 +        second2->setParent(0);
 +        QQmlEngine::setObjectOwnership(first1, QQmlEngine::JavaScriptOwnership);
 +        QQmlEngine::setObjectOwnership(second1, QQmlEngine::JavaScriptOwnership);
 +        QQmlEngine::setObjectOwnership(first2, QQmlEngine::JavaScriptOwnership);
 +        QQmlEngine::setObjectOwnership(second2, QQmlEngine::JavaScriptOwnership);
 +        gc(engine);
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +        QCOMPARE(dtorCount, 4); // circular references shouldn't keep them alive.
 +        delete object1;
 +        delete object2;
 +        hrmEngine1.collectGarbage();
 +        hrmEngine2.collectGarbage();
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +        QCOMPARE(dtorCount, 6);
 +    }
 +
 +    dtorCount = 0;
 +    {
 +        // multiple engine interaction - linear reference with engine deletion
 +        QQmlEngine *hrmEngine1 = new QQmlEngine;
 +        QQmlEngine *hrmEngine2 = new QQmlEngine;
 +        QQmlComponent component1(hrmEngine1, testFileUrl("handleReferenceManagement.handle.1.qml"));
 +        QQmlComponent component2(hrmEngine2, testFileUrl("handleReferenceManagement.handle.1.qml"));
 +        QObject *object1 = component1.create();
 +        QObject *object2 = component2.create();
 +        QVERIFY(object1 != 0);
 +        QVERIFY(object2 != 0);
 +        CircularReferenceHandle *crh1 = object1->findChild<CircularReferenceHandle*>("crh");
 +        CircularReferenceHandle *crh2 = object2->findChild<CircularReferenceHandle*>("crh");
 +        QVERIFY(crh1 != 0);
 +        QVERIFY(crh2 != 0);
 +        crh1->setEngine(hrmEngine1);
 +        crh2->setEngine(hrmEngine2);
 +        crh1->setDtorCount(&dtorCount);
 +        crh2->setDtorCount(&dtorCount);
 +        QMetaObject::invokeMethod(object1, "createReference");
 +        QMetaObject::invokeMethod(object2, "createReference");
 +        CircularReferenceHandle *first1 = object1->property("first").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *second1 = object1->property("second").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *first2 = object2->property("first").value<CircularReferenceHandle*>();
 +        CircularReferenceHandle *second2 = object2->property("second").value<CircularReferenceHandle*>();
 +        QVERIFY(first1 != 0);
 +        QVERIFY(second1 != 0);
 +        QVERIFY(first2 != 0);
 +        QVERIFY(second2 != 0);
 +        first1->addReference(QQmlData::get(second1)->v8object);  // create linear reference within engine1
 +        second1->addReference(QQmlData::get(second2)->v8object); // create linear reference across engines
 +        second2->addReference(QQmlData::get(first2)->v8object);  // create linear reference within engine2
 +        // now we have to reparent and change ownership to JS.
 +        first1->setParent(crh1);
 +        second1->setParent(0);
 +        first2->setParent(0);
 +        second2->setParent(0);
 +        QQmlEngine::setObjectOwnership(second1, QQmlEngine::JavaScriptOwnership);
 +        QQmlEngine::setObjectOwnership(first2, QQmlEngine::JavaScriptOwnership);
 +        QQmlEngine::setObjectOwnership(second2, QQmlEngine::JavaScriptOwnership);
 +        gc(engine);
 +        QCOMPARE(dtorCount, 0);
 +        delete hrmEngine2;
 +        gc(engine);
 +        QCOMPARE(dtorCount, 0);
 +        delete object1;
 +        delete object2;
 +        hrmEngine1->collectGarbage();
 +        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +        QCoreApplication::processEvents();
 +        QCOMPARE(dtorCount, 6);
 +        delete hrmEngine1;
 +    }
 +}
 +
 +void tst_qqmlecmascript::stringArg()
 +{
 +    QQmlComponent component(&engine, testFileUrl("stringArg.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "success");
 +    QVERIFY(object->property("returnValue").toBool());
 +
 +    QString w1 = testFileUrl("stringArg.qml").toString() + QLatin1String(":45: Error: String.arg(): Invalid arguments");
 +    QTest::ignoreMessage(QtWarningMsg, w1.toAscii().constData());
 +    QMetaObject::invokeMethod(object, "failure");
 +    QVERIFY(object->property("returnValue").toBool());
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::readonlyDeclaration()
 +{
 +    QQmlComponent component(&engine, testFileUrl("readonlyDeclaration.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +}
 +
 +Q_DECLARE_METATYPE(QList<int>)
 +Q_DECLARE_METATYPE(QList<qreal>)
 +Q_DECLARE_METATYPE(QList<bool>)
 +Q_DECLARE_METATYPE(QList<QString>)
 +Q_DECLARE_METATYPE(QList<QUrl>)
 +void tst_qqmlecmascript::sequenceConversionRead()
 +{
 +    {
 +        QUrl qmlFile = testFileUrl("sequenceConversion.read.qml");
 +        QQmlComponent component(&engine, qmlFile);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco");
 +        QVERIFY(seq != 0);
 +
 +        QMetaObject::invokeMethod(object, "readSequences");
 +        QList<int> intList; intList << 1 << 2 << 3 << 4;
 +        QCOMPARE(object->property("intListLength").toInt(), intList.length());
 +        QCOMPARE(object->property("intList").value<QList<int> >(), intList);
 +        QList<qreal> qrealList; qrealList << 1.1 << 2.2 << 3.3 << 4.4;
 +        QCOMPARE(object->property("qrealListLength").toInt(), qrealList.length());
 +        QCOMPARE(object->property("qrealList").value<QList<qreal> >(), qrealList);
 +        QList<bool> boolList; boolList << true << false << true << false;
 +        QCOMPARE(object->property("boolListLength").toInt(), boolList.length());
 +        QCOMPARE(object->property("boolList").value<QList<bool> >(), boolList);
 +        QList<QString> stringList; stringList << QLatin1String("first") << QLatin1String("second") << QLatin1String("third") << QLatin1String("fourth");
 +        QCOMPARE(object->property("stringListLength").toInt(), stringList.length());
 +        QCOMPARE(object->property("stringList").value<QList<QString> >(), stringList);
 +        QList<QUrl> urlList; urlList << QUrl("http://www.example1.com") << QUrl("http://www.example2.com") << QUrl("http://www.example3.com");
 +        QCOMPARE(object->property("urlListLength").toInt(), urlList.length());
 +        QCOMPARE(object->property("urlList").value<QList<QUrl> >(), urlList);
 +        QStringList qstringList; qstringList << QLatin1String("first") << QLatin1String("second") << QLatin1String("third") << QLatin1String("fourth");
 +        QCOMPARE(object->property("qstringListLength").toInt(), qstringList.length());
 +        QCOMPARE(object->property("qstringList").value<QStringList>(), qstringList);
 +
 +        QMetaObject::invokeMethod(object, "readSequenceElements");
 +        QCOMPARE(object->property("intVal").toInt(), 2);
 +        QCOMPARE(object->property("qrealVal").toReal(), 2.2);
 +        QCOMPARE(object->property("boolVal").toBool(), false);
 +        QCOMPARE(object->property("stringVal").toString(), QString(QLatin1String("second")));
 +        QCOMPARE(object->property("urlVal").toUrl(), QUrl("http://www.example2.com"));
 +        QCOMPARE(object->property("qstringVal").toString(), QString(QLatin1String("second")));
 +
 +        QMetaObject::invokeMethod(object, "enumerateSequenceElements");
 +        QCOMPARE(object->property("enumerationMatches").toBool(), true);
 +
 +        intList.clear(); intList << 1 << 2 << 3 << 4 << 5; // set by the enumerateSequenceElements test.
 +        QQmlProperty seqProp(seq, "intListProperty");
 +        QCOMPARE(seqProp.read().value<QList<int> >(), intList);
 +        QQmlProperty seqProp2(seq, "intListProperty", &engine);
 +        QCOMPARE(seqProp2.read().value<QList<int> >(), intList);
 +
 +        QMetaObject::invokeMethod(object, "testReferenceDeletion");
 +        QCOMPARE(object->property("referenceDeletion").toBool(), true);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QUrl qmlFile = testFileUrl("sequenceConversion.read.error.qml");
 +        QQmlComponent component(&engine, qmlFile);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco");
 +        QVERIFY(seq != 0);
 +
 +        // we haven't registered QList<QPoint> as a sequence type.
 +        QString warningOne = QLatin1String("QMetaProperty::read: Unable to handle unregistered datatype 'QList<QPoint>' for property 'MySequenceConversionObject::pointListProperty'");
 +        QString warningTwo = qmlFile.toString() + QLatin1String(":18: TypeError: Cannot read property 'length' of undefined");
 +        QTest::ignoreMessage(QtWarningMsg, warningOne.toAscii().constData());
 +        QTest::ignoreMessage(QtWarningMsg, warningTwo.toAscii().constData());
 +
 +        QMetaObject::invokeMethod(object, "performTest");
 +
 +        // QList<QPoint> has not been registered as a sequence type.
 +        QCOMPARE(object->property("pointListLength").toInt(), 0);
 +        QVERIFY(!object->property("pointList").isValid());
 +        QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::read: Unable to handle unregistered datatype 'QList<QPoint>' for property 'MySequenceConversionObject::pointListProperty'");
 +        QQmlProperty seqProp(seq, "pointListProperty", &engine);
 +        QVERIFY(!seqProp.read().isValid()); // not a valid/known sequence type
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::sequenceConversionWrite()
 +{
 +    {
 +        QUrl qmlFile = testFileUrl("sequenceConversion.write.qml");
 +        QQmlComponent component(&engine, qmlFile);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco");
 +        QVERIFY(seq != 0);
 +
 +        QMetaObject::invokeMethod(object, "writeSequences");
 +        QCOMPARE(object->property("success").toBool(), true);
 +
 +        QMetaObject::invokeMethod(object, "writeSequenceElements");
 +        QCOMPARE(object->property("success").toBool(), true);
 +
 +        QMetaObject::invokeMethod(object, "writeOtherElements");
 +        QCOMPARE(object->property("success").toBool(), true);
 +
 +        QMetaObject::invokeMethod(object, "testReferenceDeletion");
 +        QCOMPARE(object->property("referenceDeletion").toBool(), true);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QUrl qmlFile = testFileUrl("sequenceConversion.write.error.qml");
 +        QQmlComponent component(&engine, qmlFile);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        MySequenceConversionObject *seq = object->findChild<MySequenceConversionObject*>("msco");
 +        QVERIFY(seq != 0);
 +
 +        // we haven't registered QList<QPoint> as a sequence type, so writing shouldn't work.
 +        QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QVariantList to void");
 +        QTest::ignoreMessage(QtWarningMsg, warningOne.toAscii().constData());
 +
 +        QMetaObject::invokeMethod(object, "performTest");
 +
 +        QList<QPoint> pointList; pointList << QPoint(1, 2) << QPoint(3, 4) << QPoint(5, 6); // original values, shouldn't have changed
 +        QCOMPARE(seq->pointListProperty(), pointList);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::sequenceConversionArray()
 +{
 +    // ensure that in JS the returned sequences act just like normal JS Arrays.
 +    QUrl qmlFile = testFileUrl("sequenceConversion.array.qml");
 +    QQmlComponent component(&engine, qmlFile);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "indexedAccess");
 +    QVERIFY(object->property("success").toBool());
 +    QMetaObject::invokeMethod(object, "arrayOperations");
 +    QVERIFY(object->property("success").toBool());
 +    QMetaObject::invokeMethod(object, "testEqualitySemantics");
 +    QVERIFY(object->property("success").toBool());
 +    QMetaObject::invokeMethod(object, "testReferenceDeletion");
 +    QCOMPARE(object->property("referenceDeletion").toBool(), true);
 +    delete object;
 +}
 +
 +
 +void tst_qqmlecmascript::sequenceConversionIndexes()
 +{
 +    // ensure that we gracefully fail if unsupported index values are specified.
 +    // Qt container classes only support non-negative, signed integer index values.
 +    QUrl qmlFile = testFileUrl("sequenceConversion.indexes.qml");
 +    QQmlComponent component(&engine, qmlFile);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QString w1 = qmlFile.toString() + QLatin1String(":34: Index out of range during length set");
 +    QString w2 = qmlFile.toString() + QLatin1String(":41: Index out of range during indexed set");
 +    QString w3 = qmlFile.toString() + QLatin1String(":48: Index out of range during indexed get");
 +    QString w4 = qmlFile.toString() + QLatin1String(":78: std::bad_alloc during length set");
 +    QString w5 = qmlFile.toString() + QLatin1String(":83: std::bad_alloc during indexed set");
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(w1));
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(w2));
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(w3));
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(w4));
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(w5));
 +    QMetaObject::invokeMethod(object, "indexedAccess");
 +    QVERIFY(object->property("success").toBool());
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::sequenceConversionThreads()
 +{
 +    // ensure that sequence conversion operations work correctly in a worker thread
 +    // and that serialisation between the main and worker thread succeeds.
 +    QUrl qmlFile = testFileUrl("sequenceConversion.threads.qml");
 +    QQmlComponent component(&engine, qmlFile);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QMetaObject::invokeMethod(object, "testIntSequence");
 +    QTRY_VERIFY(object->property("finished").toBool());
 +    QVERIFY(object->property("success").toBool());
 +
 +    QMetaObject::invokeMethod(object, "testQrealSequence");
 +    QTRY_VERIFY(object->property("finished").toBool());
 +    QVERIFY(object->property("success").toBool());
 +
 +    QMetaObject::invokeMethod(object, "testBoolSequence");
 +    QTRY_VERIFY(object->property("finished").toBool());
 +    QVERIFY(object->property("success").toBool());
 +
 +    QMetaObject::invokeMethod(object, "testStringSequence");
 +    QTRY_VERIFY(object->property("finished").toBool());
 +    QVERIFY(object->property("success").toBool());
 +
 +    QMetaObject::invokeMethod(object, "testQStringSequence");
 +    QTRY_VERIFY(object->property("finished").toBool());
 +    QVERIFY(object->property("success").toBool());
 +
 +    QMetaObject::invokeMethod(object, "testUrlSequence");
 +    QTRY_VERIFY(object->property("finished").toBool());
 +    QVERIFY(object->property("success").toBool());
 +
 +    QMetaObject::invokeMethod(object, "testVariantSequence");
 +    QTRY_VERIFY(object->property("finished").toBool());
 +    QVERIFY(object->property("success").toBool());
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::sequenceConversionBindings()
 +{
 +    {
 +        QUrl qmlFile = testFileUrl("sequenceConversion.bindings.qml");
 +        QQmlComponent component(&engine, qmlFile);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        QList<int> intList; intList << 1 << 2 << 3 << 12 << 7;
 +        QCOMPARE(object->property("boundSequence").value<QList<int> >(), intList);
 +        QCOMPARE(object->property("boundElement").toInt(), intList.at(3));
 +        QList<int> intListTwo; intListTwo << 1 << 2 << 3 << 12 << 14;
 +        QCOMPARE(object->property("boundSequenceTwo").value<QList<int> >(), intListTwo);
 +        delete object;
 +    }
 +
 +    {
 +        QUrl qmlFile = testFileUrl("sequenceConversion.bindings.error.qml");
 +        QString warning = QString(QLatin1String("%1:17: Unable to assign QList<int> to QList<bool>")).arg(qmlFile.toString());
 +        QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
 +        QQmlComponent component(&engine, qmlFile);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::sequenceConversionCopy()
 +{
 +    QUrl qmlFile = testFileUrl("sequenceConversion.copy.qml");
 +    QQmlComponent component(&engine, qmlFile);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QMetaObject::invokeMethod(object, "testCopySequences");
 +    QCOMPARE(object->property("success").toBool(), true);
 +    QMetaObject::invokeMethod(object, "readSequenceCopyElements");
 +    QCOMPARE(object->property("success").toBool(), true);
 +    QMetaObject::invokeMethod(object, "testEqualitySemantics");
 +    QCOMPARE(object->property("success").toBool(), true);
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::assignSequenceTypes()
 +{
 +    // test binding array to sequence type property
 +    {
 +    QQmlComponent component(&engine, testFileUrl("assignSequenceTypes.1.qml"));
 +    MySequenceConversionObject *object = qobject_cast<MySequenceConversionObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->intListProperty(), (QList<int>() << 1 << 2));
 +    QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1 << 2.2));
 +    QCOMPARE(object->boolListProperty(), (QList<bool>() << false << true));
 +    QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl("http://www.example1.com") << QUrl("http://www.example2.com")));
 +    QCOMPARE(object->stringListProperty(), (QList<QString>() << QLatin1String("one") << QLatin1String("two")));
 +    QCOMPARE(object->qstringListProperty(), (QStringList() << QLatin1String("one") << QLatin1String("two")));
 +    delete object;
 +    }
 +
 +    // test binding literal to sequence type property
 +    {
 +    QQmlComponent component(&engine, testFileUrl("assignSequenceTypes.2.qml"));
 +    MySequenceConversionObject *object = qobject_cast<MySequenceConversionObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->intListProperty(), (QList<int>() << 1));
 +    QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1));
 +    QCOMPARE(object->boolListProperty(), (QList<bool>() << false));
 +    QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl("http://www.example1.com")));
 +    QCOMPARE(object->stringListProperty(), (QList<QString>() << QLatin1String("one")));
 +    QCOMPARE(object->qstringListProperty(), (QStringList() << QLatin1String("two")));
 +    delete object;
 +    }
 +
 +    // test binding single value to sequence type property
 +    {
 +    QQmlComponent component(&engine, testFileUrl("assignSequenceTypes.3.qml"));
 +    MySequenceConversionObject *object = qobject_cast<MySequenceConversionObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->intListProperty(), (QList<int>() << 1));
 +    QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1));
 +    QCOMPARE(object->boolListProperty(), (QList<bool>() << false));
 +    QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl(testFileUrl("example.html"))));
 +    delete object;
 +    }
 +
 +    // test assigning array to sequence type property in js function
 +    {
 +    QQmlComponent component(&engine, testFileUrl("assignSequenceTypes.4.qml"));
 +    MySequenceConversionObject *object = qobject_cast<MySequenceConversionObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->intListProperty(), (QList<int>() << 1 << 2));
 +    QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1 << 2.2));
 +    QCOMPARE(object->boolListProperty(), (QList<bool>() << false << true));
 +    QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl("http://www.example1.com") << QUrl("http://www.example2.com")));
 +    QCOMPARE(object->stringListProperty(), (QList<QString>() << QLatin1String("one") << QLatin1String("two")));
 +    QCOMPARE(object->qstringListProperty(), (QStringList() << QLatin1String("one") << QLatin1String("two")));
 +    delete object;
 +    }
 +
 +    // test assigning literal to sequence type property in js function
 +    {
 +    QQmlComponent component(&engine, testFileUrl("assignSequenceTypes.5.qml"));
 +    MySequenceConversionObject *object = qobject_cast<MySequenceConversionObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->intListProperty(), (QList<int>() << 1));
 +    QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1));
 +    QCOMPARE(object->boolListProperty(), (QList<bool>() << false));
 +    QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl("http://www.example1.com")));
 +    QCOMPARE(object->stringListProperty(), (QList<QString>() << QLatin1String("one")));
 +    QCOMPARE(object->qstringListProperty(), (QStringList() << QLatin1String("two")));
 +    delete object;
 +    }
 +
 +    // test assigning single value to sequence type property in js function
 +    {
 +    QQmlComponent component(&engine, testFileUrl("assignSequenceTypes.6.qml"));
 +    MySequenceConversionObject *object = qobject_cast<MySequenceConversionObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->intListProperty(), (QList<int>() << 1));
 +    QCOMPARE(object->qrealListProperty(), (QList<qreal>() << 1.1));
 +    QCOMPARE(object->boolListProperty(), (QList<bool>() << false));
 +    QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl(testFileUrl("example.html"))));
 +    delete object;
 +    }
 +
 +    // test QList<QUrl> literal assignment and binding assignment causes url resolution when required
 +    {
 +    QQmlComponent component(&engine, testFileUrl("assignSequenceTypes.7.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    MySequenceConversionObject *msco1 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco1"));
 +    MySequenceConversionObject *msco2 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco2"));
 +    MySequenceConversionObject *msco3 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco3"));
 +    MySequenceConversionObject *msco4 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco4"));
 +    MySequenceConversionObject *msco5 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco5"));
 +    QVERIFY(msco1 != 0 && msco2 != 0 && msco3 != 0 && msco4 != 0 && msco5 != 0);
 +    QCOMPARE(msco1->urlListProperty(), (QList<QUrl>() << QUrl(testFileUrl("example.html"))));
 +    QCOMPARE(msco2->urlListProperty(), (QList<QUrl>() << QUrl(testFileUrl("example.html"))));
 +    QCOMPARE(msco3->urlListProperty(), (QList<QUrl>() << QUrl(testFileUrl("example.html")) << QUrl(testFileUrl("example2.html"))));
 +    QCOMPARE(msco4->urlListProperty(), (QList<QUrl>() << QUrl(testFileUrl("example.html")) << QUrl(testFileUrl("example2.html"))));
 +    QCOMPARE(msco5->urlListProperty(), (QList<QUrl>() << QUrl(testFileUrl("example.html")) << QUrl(testFileUrl("example2.html"))));
 +    delete object;
 +    }
 +}
 +
 +// Test that assigning a null object works 
 +// Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
 +void tst_qqmlecmascript::nullObjectBinding()
 +{
 +    QQmlComponent component(&engine, testFileUrl("nullObjectBinding.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
 +
 +    delete object;
 +}
 +
 +// Test that bindings don't evaluate once the engine has been destroyed
 +void tst_qqmlecmascript::deletedEngine()
 +{
 +    QQmlEngine *engine = new QQmlEngine;
 +    QQmlComponent component(engine, testFileUrl("deletedEngine.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("a").toInt(), 39);
 +    object->setProperty("b", QVariant(9));
 +    QCOMPARE(object->property("a").toInt(), 117);
 +
 +    delete engine;
 +
 +    QCOMPARE(object->property("a").toInt(), 117);
 +    object->setProperty("b", QVariant(10));
 +    QCOMPARE(object->property("a").toInt(), 117);
 +
 +    delete object;
 +}
 +
 +// Test the crashing part of QTBUG-9705
 +void tst_qqmlecmascript::libraryScriptAssert()
 +{
 +    QQmlComponent component(&engine, testFileUrl("libraryScriptAssert.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::variantsAssignedUndefined()
 +{
 +    QQmlComponent component(&engine, testFileUrl("variantsAssignedUndefined.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test1").toInt(), 10);
 +    QCOMPARE(object->property("test2").toInt(), 11);
 +
 +    object->setProperty("runTest", true);
 +
 +    QCOMPARE(object->property("test1"), QVariant());
 +    QCOMPARE(object->property("test2"), QVariant());
 +
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::qtbug_9792()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtbug_9792.qml"));
 +
 +    QQmlContext *context = new QQmlContext(engine.rootContext());
 +
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
 +    QVERIFY(object != 0);
 +
 +    QTest::ignoreMessage(QtDebugMsg, "Hello world!");
 +    object->basicSignal();
 +
 +    delete context;
 +
 +    transientErrorsMsgCount = 0;
 +    QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
 +
 +    object->basicSignal();
 +    
 +    qInstallMsgHandler(old);
 +
 +    QCOMPARE(transientErrorsMsgCount, 0);
 +
 +    delete object;
 +}
 +
 +// Verifies that QQmlGuard<>s used in the vmemetaobject are cleaned correctly
 +void tst_qqmlecmascript::qtcreatorbug_1289()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtcreatorbug_1289.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QObject *nested = qvariant_cast<QObject *>(o->property("object"));
 +    QVERIFY(nested != 0);
 +
 +    QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
 +
 +    delete nested;
 +    nested = qvariant_cast<QObject *>(o->property("object"));
 +    QVERIFY(nested == 0);
 +
 +    // If the bug is present, the next line will crash
 +    delete o;
 +}
 +
 +// Test that we shut down without stupid warnings
 +void tst_qqmlecmascript::noSpuriousWarningsAtShutdown()
 +{
 +    {
 +    QQmlComponent component(&engine, testFileUrl("noSpuriousWarningsAtShutdown.qml"));
 +
 +    QObject *o = component.create();
 +
 +    transientErrorsMsgCount = 0;
 +    QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
 +
 +    delete o;
 +
 +    qInstallMsgHandler(old);
 +
 +    QCOMPARE(transientErrorsMsgCount, 0);
 +    }
 +
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("noSpuriousWarningsAtShutdown.2.qml"));
 +
 +    QObject *o = component.create();
 +
 +    transientErrorsMsgCount = 0;
 +    QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
 +
 +    delete o;
 +
 +    qInstallMsgHandler(old);
 +
 +    QCOMPARE(transientErrorsMsgCount, 0);
 +    }
 +}
 +
 +void tst_qqmlecmascript::canAssignNullToQObject()
 +{
 +    {
 +    QQmlComponent component(&engine, testFileUrl("canAssignNullToQObject.1.qml"));
 +
 +    MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(o != 0);
 +
 +    QVERIFY(o->objectProperty() != 0);
 +
 +    o->setProperty("runTest", true);
 +
 +    QVERIFY(o->objectProperty() == 0);
 +
 +    delete o;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("canAssignNullToQObject.2.qml"));
 +
 +    MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(o != 0);
 +
 +    QVERIFY(o->objectProperty() == 0);
 +
 +    delete o;
 +    }
 +}
 +
 +void tst_qqmlecmascript::functionAssignment_fromBinding()
 +{
 +    QQmlComponent component(&engine, testFileUrl("functionAssignment.1.qml"));
 +
 +    QString url = component.url().toString();
 +    QString warning = url + ":4: Unable to assign a function to a property.";
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 +    
 +    MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(o != 0);
 +
 +    QVERIFY(!o->property("a").isValid());
 +
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::functionAssignment_fromJS()
 +{
 +    QFETCH(QString, triggerProperty);
 +
 +    QQmlComponent component(&engine, testFileUrl("functionAssignment.2.qml"));
 +    QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
 +
 +    MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(o != 0);
 +    QVERIFY(!o->property("a").isValid());
 +
 +    o->setProperty("aNumber", QVariant(5));
 +    o->setProperty(triggerProperty.toUtf8().constData(), true);
 +    QCOMPARE(o->property("a"), QVariant(50));
 +
 +    o->setProperty("aNumber", QVariant(10));
 +    QCOMPARE(o->property("a"), QVariant(100));
 +
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::functionAssignment_fromJS_data()
 +{
 +    QTest::addColumn<QString>("triggerProperty");
 +
 +    QTest::newRow("assign to property") << "assignToProperty";
 +    QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
 +
 +    QTest::newRow("assign to value type") << "assignToValueType";
 +
 +    QTest::newRow("use 'this'") << "assignWithThis";
 +    QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
 +}
 +
 +void tst_qqmlecmascript::functionAssignmentfromJS_invalid()
 +{
 +    QQmlComponent component(&engine, testFileUrl("functionAssignment.2.qml"));
 +    QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
 +
 +    MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(o != 0);
 +    QVERIFY(!o->property("a").isValid());
 +
 +    o->setProperty("assignFuncWithoutReturn", true);
 +    QVERIFY(!o->property("a").isValid());
 +
 +    QString url = component.url().toString();
 +    QString warning = url + ":67: Unable to assign QString to int";
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 +    o->setProperty("assignWrongType", true);
 +
 +    warning = url + ":71: Unable to assign QString to int";
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 +    o->setProperty("assignWrongTypeToValueType", true);
 +
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::eval()
 +{
 +    QQmlComponent component(&engine, testFileUrl("eval.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test1").toBool(), true);
 +    QCOMPARE(o->property("test2").toBool(), true);
 +    QCOMPARE(o->property("test3").toBool(), true);
 +    QCOMPARE(o->property("test4").toBool(), true);
 +    QCOMPARE(o->property("test5").toBool(), true);
 +
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::function()
 +{
 +    QQmlComponent component(&engine, testFileUrl("function.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test1").toBool(), true);
 +    QCOMPARE(o->property("test2").toBool(), true);
 +    QCOMPARE(o->property("test3").toBool(), true);
 +
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::functionException()
 +{
 +    // QTBUG-24037 - shouldn't crash.
 +    QString errstr = testFileUrl("v8functionException.qml").toString() + QLatin1String(":13: SyntaxError: Unexpected token ILLEGAL");
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(errstr));
 +    QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Exception occurred during compilation of function: dynamicSlot()");
 +    QQmlComponent component(&engine, testFileUrl("v8functionException.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QMetaObject::invokeMethod(o, "dynamicSlot");
 +    delete o;
 +}
 +
 +// Test the "Qt.include" method
 +void tst_qqmlecmascript::include()
 +{
 +    // Non-library relative include
 +    {
 +    QQmlComponent component(&engine, testFileUrl("include.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test0").toInt(), 99);
 +    QCOMPARE(o->property("test1").toBool(), true);
 +    QCOMPARE(o->property("test2").toBool(), true);
 +    QCOMPARE(o->property("test2_1").toBool(), true);
 +    QCOMPARE(o->property("test3").toBool(), true);
 +    QCOMPARE(o->property("test3_1").toBool(), true);
 +
 +    delete o;
 +    }
 +
 +    // Library relative include
 +    {
 +    QQmlComponent component(&engine, testFileUrl("include_shared.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test0").toInt(), 99);
 +    QCOMPARE(o->property("test1").toBool(), true);
 +    QCOMPARE(o->property("test2").toBool(), true);
 +    QCOMPARE(o->property("test2_1").toBool(), true);
 +    QCOMPARE(o->property("test3").toBool(), true);
 +    QCOMPARE(o->property("test3_1").toBool(), true);
 +
 +    delete o;
 +    }
 +
 +    // Callback
 +    {
 +    QQmlComponent component(&engine, testFileUrl("include_callback.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test1").toBool(), true);
 +    QCOMPARE(o->property("test2").toBool(), true);
 +    QCOMPARE(o->property("test3").toBool(), true);
 +    QCOMPARE(o->property("test4").toBool(), true);
 +    QCOMPARE(o->property("test5").toBool(), true);
 +    QCOMPARE(o->property("test6").toBool(), true);
 +
 +    delete o;
 +    }
 +
 +    // Including file with ".pragma library"
 +    {
 +    QQmlComponent component(&engine, testFileUrl("include_pragma.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test1").toInt(), 100);
 +
 +    delete o;
 +    }
 +
 +    // Remote - success
 +    {
 +    TestHTTPServer server(8111);
 +    QVERIFY(server.isValid());
 +    server.serveDirectory(dataDirectory());
 +
 +    QQmlComponent component(&engine, testFileUrl("include_remote.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QTRY_VERIFY(o->property("done").toBool() == true);
 +    QTRY_VERIFY(o->property("done2").toBool() == true);
 +
 +    QCOMPARE(o->property("test1").toBool(), true);
 +    QCOMPARE(o->property("test2").toBool(), true);
 +    QCOMPARE(o->property("test3").toBool(), true);
 +    QCOMPARE(o->property("test4").toBool(), true);
 +    QCOMPARE(o->property("test5").toBool(), true);
 +
 +    QCOMPARE(o->property("test6").toBool(), true);
 +    QCOMPARE(o->property("test7").toBool(), true);
 +    QCOMPARE(o->property("test8").toBool(), true);
 +    QCOMPARE(o->property("test9").toBool(), true);
 +    QCOMPARE(o->property("test10").toBool(), true);
 +
 +    delete o;
 +    }
 +
 +    // Remote - error
 +    {
 +    TestHTTPServer server(8111);
 +    QVERIFY(server.isValid());
 +    server.serveDirectory(dataDirectory());
 +
 +    QQmlComponent component(&engine, testFileUrl("include_remote_missing.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QTRY_VERIFY(o->property("done").toBool() == true);
 +
 +    QCOMPARE(o->property("test1").toBool(), true);
 +    QCOMPARE(o->property("test2").toBool(), true);
 +    QCOMPARE(o->property("test3").toBool(), true);
 +
 +    delete o;
 +    }
 +}
 +
 +void tst_qqmlecmascript::signalHandlers()
 +{
 +    QQmlComponent component(&engine, testFileUrl("signalHandlers.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QVERIFY(o->property("count").toInt() == 0);
 +    QMetaObject::invokeMethod(o, "testSignalCall");
 +    QCOMPARE(o->property("count").toInt(), 1);
 +
 +    QMetaObject::invokeMethod(o, "testSignalHandlerCall");
 +    QCOMPARE(o->property("count").toInt(), 1);
 +    QCOMPARE(o->property("errorString").toString(), QLatin1String("TypeError: Property 'onTestSignal' of object [object Object] is not a function"));
 +
 +    QVERIFY(o->property("funcCount").toInt() == 0);
 +    QMetaObject::invokeMethod(o, "testSignalConnection");
 +    QCOMPARE(o->property("funcCount").toInt(), 1);
 +
 +    QMetaObject::invokeMethod(o, "testSignalHandlerConnection");
 +    QCOMPARE(o->property("funcCount").toInt(), 2);
 +
 +    QMetaObject::invokeMethod(o, "testSignalDefined");
 +    QCOMPARE(o->property("definedResult").toBool(), true);
 +
 +    QMetaObject::invokeMethod(o, "testSignalHandlerDefined");
 +    QCOMPARE(o->property("definedHandlerResult").toBool(), true);
 +
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::qtbug_10696()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtbug_10696.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::qtbug_11606()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtbug_11606.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test").toBool(), true);
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::qtbug_11600()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtbug_11600.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test").toBool(), true);
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::qtbug_21864()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtbug_21864.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test").toBool(), true);
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::rewriteMultiLineStrings()
 +{
++    {
++        // QTBUG-23387
++        QQmlComponent component(&engine, testFileUrl("rewriteMultiLineStrings.qml"));
++        QObject *o = component.create();
++        QVERIFY(o != 0);
++        QTRY_COMPARE(o->property("test").toBool(), true);
++        delete o;
++    }
++
++    {
++        QQmlComponent component(&engine, testFileUrl("rewriteMultiLineStrings_crlf.1.qml"));
++        QObject *o = component.create();
++        QVERIFY(o != 0);
++        delete o;
++    }
 +}
 +
 +void tst_qqmlecmascript::qobjectConnectionListExceptionHandling()
 +{
 +    // QTBUG-23375
 +    QQmlComponent component(&engine, testFileUrl("qobjectConnectionListExceptionHandling.qml"));
 +    QString warning = component.url().toString() + QLatin1String(":13: TypeError: Cannot read property 'undefined' of undefined");
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test").toBool(), true);
 +    delete o;
 +}
 +
 +// Reading and writing non-scriptable properties should fail
 +void tst_qqmlecmascript::nonscriptable()
 +{
 +    QQmlComponent component(&engine, testFileUrl("nonscriptable.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("readOk").toBool(), true);
 +    QCOMPARE(o->property("writeOk").toBool(), true);
 +    delete o;
 +}
 +
 +// deleteLater() should not be callable from QML
 +void tst_qqmlecmascript::deleteLater()
 +{
 +    QQmlComponent component(&engine, testFileUrl("deleteLater.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test").toBool(), true);
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::in()
 +{
 +    QQmlComponent component(&engine, testFileUrl("in.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test1").toBool(), true);
 +    QCOMPARE(o->property("test2").toBool(), true);
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::typeOf()
 +{
 +    QQmlComponent component(&engine, testFileUrl("typeOf.qml"));
 +
 +    // These warnings should not happen once QTBUG-21864 is fixed
 +    QString warning1 = component.url().toString() + QLatin1String(":16: Error: Cannot assign [undefined] to QString");
 +    QString warning2 = component.url().resolved(QUrl("typeOf.js")).toString() + QLatin1String(":1: ReferenceError: Can't find variable: a");
 +
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QEXPECT_FAIL("", "QTBUG-21864", Abort);
 +    QCOMPARE(o->property("test1").toString(), QLatin1String("undefined"));
 +    QCOMPARE(o->property("test2").toString(), QLatin1String("object"));
 +    QCOMPARE(o->property("test3").toString(), QLatin1String("number"));
 +    QCOMPARE(o->property("test4").toString(), QLatin1String("string"));
 +    QCOMPARE(o->property("test5").toString(), QLatin1String("function"));
 +    QCOMPARE(o->property("test6").toString(), QLatin1String("object"));
 +    QCOMPARE(o->property("test7").toString(), QLatin1String("undefined"));
 +    QCOMPARE(o->property("test8").toString(), QLatin1String("boolean"));
 +    QCOMPARE(o->property("test9").toString(), QLatin1String("object"));
 +
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::sharedAttachedObject()
 +{
 +    QQmlComponent component(&engine, testFileUrl("sharedAttachedObject.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test1").toBool(), true);
 +    QCOMPARE(o->property("test2").toBool(), true);
 +    delete o;
 +}
 +
 +// QTBUG-13999
 +void tst_qqmlecmascript::objectName()
 +{
 +    QQmlComponent component(&engine, testFileUrl("objectName.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test1").toString(), QString("hello"));
 +    QCOMPARE(o->property("test2").toString(), QString("ell"));
 +
 +    o->setObjectName("world");
 +
 +    QCOMPARE(o->property("test1").toString(), QString("world"));
 +    QCOMPARE(o->property("test2").toString(), QString("orl"));
 +
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::writeRemovesBinding()
 +{
 +    QQmlComponent component(&engine, testFileUrl("writeRemovesBinding.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test").toBool(), true);
 +
 +    delete o;
 +}
 +
 +// Test bindings assigned to alias properties actually assign to the alias' target
 +void tst_qqmlecmascript::aliasBindingsAssignCorrectly()
 +{
 +    QQmlComponent component(&engine, testFileUrl("aliasBindingsAssignCorrectly.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test").toBool(), true);
 +
 +    delete o;
 +}
 +
 +// Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
 +void tst_qqmlecmascript::aliasBindingsOverrideTarget()
 +{
 +    { 
 +    QQmlComponent component(&engine, testFileUrl("aliasBindingsOverrideTarget.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test").toBool(), true);
 +
 +    delete o;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("aliasBindingsOverrideTarget.2.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test").toBool(), true);
 +
 +    delete o;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("aliasBindingsOverrideTarget.3.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test").toBool(), true);
 +
 +    delete o;
 +    }
 +}
 +
 +// Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
 +void tst_qqmlecmascript::aliasWritesOverrideBindings()
 +{
 +    {
 +    QQmlComponent component(&engine, testFileUrl("aliasWritesOverrideBindings.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test").toBool(), true);
 +
 +    delete o;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("aliasWritesOverrideBindings.2.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test").toBool(), true);
 +
 +    delete o;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("aliasWritesOverrideBindings.3.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test").toBool(), true);
 +
 +    delete o;
 +    }
 +}
 +
 +// Allow an alais to a composite element
 +// QTBUG-20200
 +void tst_qqmlecmascript::aliasToCompositeElement()
 +{
 +    QQmlComponent component(&engine, testFileUrl("aliasToCompositeElement.qml"));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::qtbug_20344()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtbug_20344.qml"));
 +
 +    QString warning = component.url().toString() + ":5: Error: Exception thrown from within QObject slot";
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::revisionErrors()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("metaobjectRevisionErrors.qml"));
 +        QString url = component.url().toString();
 +
 +        QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
 +        QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
 +        QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
 +
 +        QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
 +        QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
 +        QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
 +        MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
 +        QVERIFY(object != 0);
 +        delete object;
 +    }
 +    {
 +        QQmlComponent component(&engine, testFileUrl("metaobjectRevisionErrors2.qml"));
 +        QString url = component.url().toString();
 +
 +        // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
 +        // method2, prop2 from MyRevisionedClass not available
 +        // method4, prop4 from MyRevisionedSubclass not available
 +        QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
 +        QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
 +        QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
 +        QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
 +        QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
 +
 +        QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
 +        QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
 +        QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
 +        QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
 +        QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
 +        MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
 +        QVERIFY(object != 0);
 +        delete object;
 +    }
 +    {
 +        QQmlComponent component(&engine, testFileUrl("metaobjectRevisionErrors3.qml"));
 +        QString url = component.url().toString();
 +
 +        // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
 +        // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
 +        QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
 +        QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
 +        QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
 +        QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
 +        QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
 +        QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
 +        MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
 +        QVERIFY(object != 0);
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::revision()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("metaobjectRevision.qml"));
 +        QString url = component.url().toString();
 +
 +        MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
 +        QVERIFY(object != 0);
 +        delete object;
 +    }
 +    {
 +        QQmlComponent component(&engine, testFileUrl("metaobjectRevision2.qml"));
 +        QString url = component.url().toString();
 +
 +        MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
 +        QVERIFY(object != 0);
 +        delete object;
 +    }
 +    {
 +        QQmlComponent component(&engine, testFileUrl("metaobjectRevision3.qml"));
 +        QString url = component.url().toString();
 +
 +        MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
 +        QVERIFY(object != 0);
 +        delete object;
 +    }
 +    // Test that non-root classes can resolve revisioned methods
 +    {
 +        QQmlComponent component(&engine, testFileUrl("metaobjectRevision4.qml"));
 +
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->property("test").toReal(), 11.);
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::realToInt()
 +{
 +    QQmlComponent component(&engine, testFileUrl("realToInt.qml"));
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QMetaObject::invokeMethod(object, "test1");
 +    QCOMPARE(object->value(), int(4));
 +    QMetaObject::invokeMethod(object, "test2");
 +    QCOMPARE(object->value(), int(8));
 +}
 +
 +void tst_qqmlecmascript::urlProperty()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("urlProperty.1.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +        QVERIFY(object != 0);
 +        object->setStringProperty("http://qt-project.org");
 +        QCOMPARE(object->urlProperty(), QUrl("http://qt-project.org/index.html"));
 +        QCOMPARE(object->intProperty(), 123);
 +        QCOMPARE(object->value(), 1);
 +        QCOMPARE(object->property("result").toBool(), true);
 +    }
 +}
 +
 +void tst_qqmlecmascript::urlPropertyWithEncoding()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("urlProperty.2.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +        QVERIFY(object != 0);
 +        object->setStringProperty("http://qt-project.org");
 +        QUrl encoded;
 +        encoded.setEncodedUrl("http://qt-project.org/?get%3cDATA%3e", QUrl::TolerantMode);
 +        QCOMPARE(object->urlProperty(), encoded);
 +        QCOMPARE(object->value(), 0);   // Interpreting URL as string yields canonicalised version
 +        QCOMPARE(object->property("result").toBool(), true);
 +    }
 +}
 +
 +void tst_qqmlecmascript::urlListPropertyWithEncoding()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("urlListProperty.qml"));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        MySequenceConversionObject *msco1 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco1"));
 +        MySequenceConversionObject *msco2 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco2"));
 +        MySequenceConversionObject *msco3 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco3"));
 +        MySequenceConversionObject *msco4 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco4"));
 +        QVERIFY(msco1 != 0 && msco2 != 0 && msco3 != 0 && msco4 != 0);
 +        QUrl encoded;
 +        encoded.setEncodedUrl("http://qt-project.org/?get%3cDATA%3e", QUrl::TolerantMode);
 +        QCOMPARE(msco1->urlListProperty(), (QList<QUrl>() << encoded));
 +        QCOMPARE(msco2->urlListProperty(), (QList<QUrl>() << encoded));
 +        QCOMPARE(msco3->urlListProperty(), (QList<QUrl>() << encoded << encoded));
 +        QCOMPARE(msco4->urlListProperty(), (QList<QUrl>() << encoded << encoded));
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlecmascript::dynamicString()
 +{
 +    QQmlComponent component(&engine, testFileUrl("dynamicString.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->property("stringProperty").toString(),
 +             QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
 +}
 +
 +void tst_qqmlecmascript::automaticSemicolon()
 +{
 +    QQmlComponent component(&engine, testFileUrl("automaticSemicolon.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +}
 +
 +void tst_qqmlecmascript::unaryExpression()
 +{
 +    QQmlComponent component(&engine, testFileUrl("unaryExpression.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +}
 +
 +// Makes sure that a binding isn't double re-evaluated when it depends on the same variable twice
 +void tst_qqmlecmascript::doubleEvaluate()
 +{
 +    QQmlComponent component(&engine, testFileUrl("doubleEvaluate.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    WriteCounter *wc = qobject_cast<WriteCounter *>(object);
 +    QVERIFY(wc != 0);
 +    QCOMPARE(wc->count(), 1);
 +
 +    wc->setProperty("x", 9);
 +
 +    QCOMPARE(wc->count(), 2);
 +
 +    delete object;
 +}
 +
 +static QStringList messages;
 +static void captureMsgHandler(QtMsgType, const char *msg)
 +{
 +    messages.append(QLatin1String(msg));
 +}
 +
 +void tst_qqmlecmascript::nonNotifyable()
 +{
 +    QV4Compiler::enableV4(false);
 +    QQmlComponent component(&engine, testFileUrl("nonNotifyable.qml"));
 +    QV4Compiler::enableV4(true);
 +
 +    QtMsgHandler old = qInstallMsgHandler(captureMsgHandler);
 +    messages.clear();
 +    QObject *object = component.create();
 +    qInstallMsgHandler(old);
 +
 +    QVERIFY(object != 0);
 +
 +    QString expected1 = QLatin1String("QQmlExpression: Expression ") +
 +                        component.url().toString() +
 +                        QLatin1String(":5 depends on non-NOTIFYable properties:");
 +    QString expected2 = QLatin1String("    ") +
 +                        QLatin1String(object->metaObject()->className()) +
 +                        QLatin1String("::value");
 +
 +    QCOMPARE(messages.length(), 2);
 +    QCOMPARE(messages.at(0), expected1);
 +    QCOMPARE(messages.at(1), expected2);
 +
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::forInLoop()
 +{
 +    QQmlComponent component(&engine, testFileUrl("forInLoop.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QMetaObject::invokeMethod(object, "listProperty");
 +
 +    QStringList r = object->property("listResult").toString().split("|", QString::SkipEmptyParts);
 +    QCOMPARE(r.size(), 3);
 +    QCOMPARE(r[0],QLatin1String("0=obj1"));
 +    QCOMPARE(r[1],QLatin1String("1=obj2"));
 +    QCOMPARE(r[2],QLatin1String("2=obj3"));
 +
 +    //TODO: should test for in loop for other objects (such as QObjects) as well.
 +
 +    delete object;
 +}
 +
 +// An object the binding depends on is deleted while the binding is still running
 +void tst_qqmlecmascript::deleteWhileBindingRunning()
 +{
 +    QQmlComponent component(&engine, testFileUrl("deleteWhileBindingRunning.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    delete object;
 +}
 +
 +void tst_qqmlecmascript::qtbug_22679()
 +{
 +    MyQmlObject object;
 +    object.setStringProperty(QLatin1String("Please work correctly"));
 +    engine.rootContext()->setContextProperty("contextProp", &object);
 +
 +    QQmlComponent component(&engine, testFileUrl("qtbug_22679.qml"));
 +    qRegisterMetaType<QList<QQmlError> >("QList<QQmlError>");
 +    QSignalSpy warningsSpy(&engine, SIGNAL(warnings(QList<QQmlError>)));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(warningsSpy.count(), 0);
 +    delete o;
 +}
 +
 +void tst_qqmlecmascript::qtbug_22843_data()
 +{
 +    QTest::addColumn<bool>("library");
 +
 +    QTest::newRow("without .pragma library") << false;
 +    QTest::newRow("with .pragma library") << true;
 +}
 +
 +void tst_qqmlecmascript::qtbug_22843()
 +{
 +    QFETCH(bool, library);
 +
 +    QString fileName("qtbug_22843");
 +    if (library)
 +        fileName += QLatin1String(".library");
 +    fileName += QLatin1String(".qml");
 +
 +    QQmlComponent component(&engine, testFileUrl(fileName));
 +    QString url = component.url().toString();
 +    QString warning1 = url.left(url.length()-3) + QLatin1String("js:4: SyntaxError: Unexpected token )");
 +    QString warning2 = url + QLatin1String(":5: TypeError: Object [object Object] has no method 'func'");
 +
 +    qRegisterMetaType<QList<QQmlError> >("QList<QQmlError>");
 +    QSignalSpy warningsSpy(&engine, SIGNAL(warnings(QList<QQmlError>)));
 +    for (int x = 0; x < 3; ++x) {
 +        warningsSpy.clear();
 +        // For libraries, only the first import attempt should produce a
 +        // SyntaxError warning; subsequent component creation should not
 +        // attempt to reload the script.
 +        bool expectSyntaxError = !library || (x == 0);
 +        if (expectSyntaxError)
 +            QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
 +        QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        QCOMPARE(warningsSpy.count(), 1 + (expectSyntaxError?1:0));
 +        delete object;
 +    }
 +}
 +
 +
 +void tst_qqmlecmascript::switchStatement()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("switchStatement.1.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        // `object->value()' is the number of executed statements
 +
 +        object->setStringProperty("A");
 +        QCOMPARE(object->value(), 5);
 +
 +        object->setStringProperty("S");
 +        QCOMPARE(object->value(), 3);
 +
 +        object->setStringProperty("D");
 +        QCOMPARE(object->value(), 3);
 +
 +        object->setStringProperty("F");
 +        QCOMPARE(object->value(), 4);
 +
 +        object->setStringProperty("something else");
 +        QCOMPARE(object->value(), 1);
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("switchStatement.2.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        // `object->value()' is the number of executed statements
 +
 +        object->setStringProperty("A");
 +        QCOMPARE(object->value(), 5);
 +
 +        object->setStringProperty("S");
 +        QCOMPARE(object->value(), 3);
 +
 +        object->setStringProperty("D");
 +        QCOMPARE(object->value(), 3);
 +
 +        object->setStringProperty("F");
 +        QCOMPARE(object->value(), 3);
 +
 +        object->setStringProperty("something else");
 +        QCOMPARE(object->value(), 4);
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("switchStatement.3.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        // `object->value()' is the number of executed statements
 +
 +        object->setStringProperty("A");
 +        QCOMPARE(object->value(), 5);
 +
 +        object->setStringProperty("S");
 +        QCOMPARE(object->value(), 3);
 +
 +        object->setStringProperty("D");
 +        QCOMPARE(object->value(), 3);
 +
 +        object->setStringProperty("F");
 +        QCOMPARE(object->value(), 3);
 +
 +        object->setStringProperty("something else");
 +        QCOMPARE(object->value(), 6);
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("switchStatement.4.qml"));
 +
 +        QString warning = component.url().toString() + ":4: Unable to assign [undefined] to int";
 +        QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        // `object->value()' is the number of executed statements
 +
 +        object->setStringProperty("A");
 +        QCOMPARE(object->value(), 5);
 +
 +        object->setStringProperty("S");
 +        QCOMPARE(object->value(), 3);
 +
 +        object->setStringProperty("D");
 +        QCOMPARE(object->value(), 3);
 +
 +        object->setStringProperty("F");
 +        QCOMPARE(object->value(), 3);
 +
 +        QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +
 +        object->setStringProperty("something else");
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("switchStatement.5.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        // `object->value()' is the number of executed statements
 +
 +        object->setStringProperty("A");
 +        QCOMPARE(object->value(), 1);
 +
 +        object->setStringProperty("S");
 +        QCOMPARE(object->value(), 1);
 +
 +        object->setStringProperty("D");
 +        QCOMPARE(object->value(), 1);
 +
 +        object->setStringProperty("F");
 +        QCOMPARE(object->value(), 1);
 +
 +        object->setStringProperty("something else");
 +        QCOMPARE(object->value(), 1);
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("switchStatement.6.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        // `object->value()' is the number of executed statements
 +
 +        object->setStringProperty("A");
 +        QCOMPARE(object->value(), 123);
 +
 +        object->setStringProperty("S");
 +        QCOMPARE(object->value(), 123);
 +
 +        object->setStringProperty("D");
 +        QCOMPARE(object->value(), 321);
 +
 +        object->setStringProperty("F");
 +        QCOMPARE(object->value(), 321);
 +
 +        object->setStringProperty("something else");
 +        QCOMPARE(object->value(), 0);
 +    }
 +}
 +
 +void tst_qqmlecmascript::withStatement()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("withStatement.1.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->value(), 123);
 +    }
 +}
 +
 +void tst_qqmlecmascript::tryStatement()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("tryStatement.1.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->value(), 123);
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("tryStatement.2.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->value(), 321);
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("tryStatement.3.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->value(), 1);
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("tryStatement.4.qml"));
 +        MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->value(), 1);
 +    }
 +}
 +
 +class CppInvokableWithQObjectDerived : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    CppInvokableWithQObjectDerived() {}
 +    ~CppInvokableWithQObjectDerived() {}
 +
 +    Q_INVOKABLE MyQmlObject *createMyQmlObject(QString data)
 +    {
 +        MyQmlObject *obj = new MyQmlObject();
 +        obj->setStringProperty(data);
 +        return obj;
 +    }
 +
 +    Q_INVOKABLE QString getStringProperty(MyQmlObject *obj)
 +    {
 +        return obj->stringProperty();
 +    }
 +};
 +
 +void tst_qqmlecmascript::invokableWithQObjectDerived()
 +{
 +    CppInvokableWithQObjectDerived invokable;
 +
 +    {
 +    QQmlEngine engine;
 +    engine.rootContext()->setContextProperty("invokable", &invokable);
 +
 +    QQmlComponent component(&engine, testFileUrl("qobjectDerivedArgument.qml"));
 +
 +    QObject *object = component.create();
 +
 +    QVERIFY(object != 0);
 +    QVERIFY(object->property("result").value<bool>() == true);
 +
 +    delete object;
 +    }
 +}
 +
 +QTEST_MAIN(tst_qqmlecmascript)
 +
 +#include "tst_qqmlecmascript.moc"
index 07b89af,0000000..d076f03
mode 100644,000000..100644
--- /dev/null
@@@ -1,678 -1,0 +1,678 @@@
-         << "27\t\tSTORE_SIGNAL\t\t2\t3\t\t\"console.log(1921)\""
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include <qtest.h>
 +#include <private/qqmlcompiler_p.h>
 +
 +class tst_qqmlinstruction : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    tst_qqmlinstruction() {}
 +
 +private slots:
 +    void dump();
 +
 +    void point();
 +    void pointf();
 +    void size();
 +    void sizef();
 +    void rect();
 +    void rectf();
 +    void vector3d();
 +    void vector4d();
 +    void time();
 +};
 +
 +static QStringList messages;
 +static void msgHandler(QtMsgType, const char *msg)
 +{
 +    messages << QLatin1String(msg);
 +}
 +
 +void tst_qqmlinstruction::dump()
 +{
 +    QQmlEngine engine;
 +    QQmlCompiledData *data = new QQmlCompiledData(&engine);
 +
 +    {
 +        QQmlCompiledData::Instruction::Init i;
 +        i.bindingsSize = 0;
 +        i.parserStatusSize = 3;
 +        i.contextCache = -1;
 +        i.compiledBinding = -1;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::TypeReference ref;
 +        ref.className = "Test";
 +        data->types << ref;
 +
 +        QQmlCompiledData::Instruction::CreateCppObject i;
 +        i.type = 0;
 +        i.data = -1;
 +        i.column = 10;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        data->primitives << "testId";
 +
 +        QQmlCompiledData::Instruction::SetId i;
 +        i.value = data->primitives.count() - 1;
 +        i.index = 0;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::SetDefault i;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::CreateComponent i;
 +        i.count = 3;
 +        i.column = 4;
 +        i.endLine = 14;
 +        i.metaObject = 0;
 +
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreMetaObject i;
 +        i.data = 3;
 +        i.aliasData = 6;
 +        i.propertyCache = 7;
 +
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreFloat i;
 +        i.propertyIndex = 3;
 +        i.value = 11.3;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreDouble i;
 +        i.propertyIndex = 4;
 +        i.value = 14.8;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreInteger i;
 +        i.propertyIndex = 5;
 +        i.value = 9;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreBool i;
 +        i.propertyIndex = 6;
 +        i.value = true;
 +
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        data->primitives << "Test String";
 +        QQmlCompiledData::Instruction::StoreString i;
 +        i.propertyIndex = 7;
 +        i.value = data->primitives.count() - 1;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        data->urls << QUrl("http://www.nokia.com");
 +        QQmlCompiledData::Instruction::StoreUrl i;
 +        i.propertyIndex = 8;
 +        i.value = data->urls.count() - 1;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreColor i;
 +        i.propertyIndex = 9;
 +        i.value = 0xFF00FF00;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreDate i;
 +        i.propertyIndex = 10;
 +        i.value = 9;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreTime i;
 +        i.propertyIndex = 11;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreDateTime i;
 +        i.propertyIndex = 12;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StorePoint i;
 +        i.propertyIndex = 13;
 +        i.point.xp = 3;
 +        i.point.yp = 7;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StorePointF i;
 +        i.propertyIndex = 13;
 +        i.point.xp = 3;
 +        i.point.yp = 7;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreSize i;
 +        i.propertyIndex = 15;
 +        i.size.wd = 8;
 +        i.size.ht = 11;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreSizeF i;
 +        i.propertyIndex = 15;
 +        i.size.wd = 8;
 +        i.size.ht = 11;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreRect i;
 +        i.propertyIndex = 17;
 +        i.rect.x1 = 7;
 +        i.rect.y1 = 9;
 +        i.rect.x2 = 11;
 +        i.rect.y2 = 13;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreRectF i;
 +        i.propertyIndex = 18;
 +        i.rect.xp = 11.3;
 +        i.rect.yp = 9.8;
 +        i.rect.w = 3;
 +        i.rect.h = 2.1;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreVector3D i;
 +        i.propertyIndex = 19;
 +        i.vector.xp = 9;
 +        i.vector.yp = 3;
 +        i.vector.zp = 92;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        data->primitives << "color(1, 1, 1, 1)";
 +        QQmlCompiledData::Instruction::StoreVariant i;
 +        i.propertyIndex = 20;
 +        i.value = data->primitives.count() - 1;
 +
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreObject i;
 +        i.propertyIndex = 21;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreVariantObject i;
 +        i.propertyIndex = 22;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreInterface i;
 +        i.propertyIndex = 23;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        data->primitives << "console.log(1921)";
 +
 +        QQmlCompiledData::Instruction::StoreSignal i;
 +        i.signalIndex = 2;
 +        i.value = data->primitives.count() - 1;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreScriptString i;
 +        i.propertyIndex = 24;
 +        i.value = 3;
 +        i.scope = 1;
 +        i.bindingId = 4;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        data->primitives << "mySignal";
 +
 +        QQmlCompiledData::Instruction::AssignSignalObject i;
 +        i.signal = data->primitives.count() - 1;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::AssignCustomType i;
 +        i.propertyIndex = 25;
 +        i.primitive = 6;
 +        i.type = 9;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreBinding i;
 +        i.property.coreIndex = 26;
 +        i.value = 3;
 +        i.context = 2;
 +        i.owner = 0;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreV4Binding i;
 +        i.property = 27;
 +        i.value = 2;
 +        i.context = 4;
 +        i.owner = 0;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreValueSource i;
 +        i.property.coreIndex = 29;
 +        i.owner = 1;
 +        i.castValue = 4;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreValueInterceptor i;
 +        i.property.coreIndex = 30;
 +        i.owner = 2;
 +        i.castValue = -4;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::BeginObject i;
 +        i.castValue = 4;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreObjectQList i;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::AssignObjectList i;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::FetchAttached i;
 +        i.id = 23;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::FetchQList i;
 +        i.property = 32;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::FetchObject i;
 +        i.property = 33;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::FetchValueType i;
 +        i.property = 34;
 +        i.type = 6;
 +        i.bindingSkipList = 7;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::PopFetchedObject i;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::PopQList i;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::PopValueType i;
 +        i.property = 35;
 +        i.type = 8;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::Defer i;
 +        i.deferCount = 7;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::Defer i;
 +        i.deferCount = 7;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreImportedScript i;
 +        i.value = 2;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreVariantInteger i;
 +        i.value = 11;
 +        i.propertyIndex = 32;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreVariantDouble i;
 +        i.value = 33.7;
 +        i.propertyIndex = 19;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::Done i;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreTrString i;
 +        i.propertyIndex = 99;
 +        i.context = 3;
 +        i.text = 14;
 +        i.comment = 14;
 +        i.n = 2;
 +        data->addInstruction(i);
 +    }
 +
 +    {
 +        QQmlCompiledData::Instruction::StoreTrIdString i;
 +        i.propertyIndex = 78;
 +        i.text = 7;
 +        i.n = -1;
 +        data->addInstruction(i);
 +    }
 +
 +    QStringList expect;
 +    expect 
 +        << "Index\tOperation\t\tData1\tData2\tData3\tComments"
 +        << "-------------------------------------------------------------------------------"
 +        << "0\t\tINIT\t\t\t0\t3\t-1\t-1"
 +        << "1\t\tCREATECPP\t\t\t0\t\t\t\"Test\""
 +        << "2\t\tSETID\t\t\t0\t\t\t\"testId\""
 +        << "3\t\tSET_DEFAULT"
 +        << "4\t\tCREATE_COMPONENT\t3"
 +        << "5\t\tSTORE_META\t\t3"
 +        << "6\t\tSTORE_FLOAT\t\t3\t11.3"
 +        << "7\t\tSTORE_DOUBLE\t\t4\t14.8"
 +        << "8\t\tSTORE_INTEGER\t\t5\t9"
 +        << "9\t\tSTORE_BOOL\t\t6\ttrue"
 +        << "10\t\tSTORE_STRING\t\t7\t1\t\t\"Test String\""
 +        << "11\t\tSTORE_URL\t\t8\t0\t\tQUrl(\"http://www.nokia.com\") "
 +        << "12\t\tSTORE_COLOR\t\t9\t\t\t\"ff00ff00\""
 +        << "13\t\tSTORE_DATE\t\t10\t9"
 +        << "14\t\tSTORE_TIME\t\t11"
 +        << "15\t\tSTORE_DATETIME\t\t12"
 +        << "16\t\tSTORE_POINT\t\t13\t3\t7"
 +        << "17\t\tSTORE_POINTF\t\t13\t3\t7"
 +        << "18\t\tSTORE_SIZE\t\t15\t8\t11"
 +        << "19\t\tSTORE_SIZEF\t\t15\t8\t11"
 +        << "20\t\tSTORE_RECT\t\t17\t7\t9\t11\t13"
 +        << "21\t\tSTORE_RECTF\t\t18\t11.3\t9.8\t3\t2.1"
 +        << "22\t\tSTORE_VECTOR3D\t\t19\t9\t3\t92"
 +        << "23\t\tSTORE_VARIANT\t\t20\t2\t\t\"color(1, 1, 1, 1)\""
 +        << "24\t\tSTORE_OBJECT\t\t21"
 +        << "25\t\tSTORE_VARIANT_OBJECT\t22"
 +        << "26\t\tSTORE_INTERFACE\t\t23"
-         << "29\t\tASSIGN_SIGNAL_OBJECT\t4\t\t\t\"mySignal\""
++        << "27\t\tSTORE_SIGNAL\t\t2\t3"
 +        << "28\t\tSTORE_SCRIPT_STRING\t24\t3\t1\t4"
++        << "29\t\tASSIGN_SIGNAL_OBJECT\t4"
 +        << "30\t\tASSIGN_CUSTOMTYPE\t25\t6\t9"
 +        << "31\t\tSTORE_BINDING\t26\t3\t2"
 +        << "32\t\tSTORE_COMPILED_BINDING\t27\t2\t4"
 +        << "33\t\tSTORE_VALUE_SOURCE\t29\t4"
 +        << "34\t\tSTORE_VALUE_INTERCEPTOR\t30\t-4"
 +        << "35\t\tBEGIN\t\t\t4"
 +        << "36\t\tSTORE_OBJECT_QLIST"
 +        << "37\t\tASSIGN_OBJECT_LIST"
 +        << "38\t\tFETCH_ATTACHED\t\t23"
 +        << "39\t\tFETCH_QLIST\t\t32"
 +        << "40\t\tFETCH\t\t\t33"
 +        << "41\t\tFETCH_VALUE\t\t34\t6\t7"
 +        << "42\t\tPOP"
 +        << "43\t\tPOP_QLIST"
 +        << "44\t\tPOP_VALUE\t\t35\t8"
 +        << "45\t\tDEFER\t\t\t7"
 +        << "46\t\tDEFER\t\t\t7"
 +        << "47\t\tSTORE_IMPORTED_SCRIPT\t2"
 +        << "48\t\tSTORE_VARIANT_INTEGER\t\t32\t11"
 +        << "49\t\tSTORE_VARIANT_DOUBLE\t\t19\t33.7"
 +        << "50\t\tDONE"
 +        << "51\t\tSTORE_TR_STRING\t99\t3\t14\t14\t2"
 +        << "52\t\tSTORE_TRID_STRING\t78\t7\t-1"
 +        << "-------------------------------------------------------------------------------";
 +
 +    messages = QStringList();
 +    QtMsgHandler old = qInstallMsgHandler(msgHandler);
 +
 +    data->dumpInstructions();
 +    qInstallMsgHandler(old);
 +
 +    QCOMPARE(messages.count(), expect.count());
 +    for (int ii = 0; ii < messages.count(); ++ii) {
 +        QCOMPARE(messages.at(ii), expect.at(ii));
 +    }
 +
 +    data->release();
 +}
 +
 +void tst_qqmlinstruction::point()
 +{
 +    QCOMPARE(sizeof(QQmlInstruction::instr_storePoint::QPoint), sizeof(QPoint));
 +    QCOMPARE(Q_ALIGNOF(QQmlInstruction::instr_storePoint::QPoint), Q_ALIGNOF(QPoint));
 +
 +    QQmlInstruction i;
 +    i.storePoint.point.xp = 8;
 +    i.storePoint.point.yp = 11;
 +
 +    const QPoint &point = (const QPoint &)(i.storePoint.point);
 +    QCOMPARE(point.x(), 8);
 +    QCOMPARE(point.y(), 11);
 +}
 +
 +void tst_qqmlinstruction::pointf()
 +{
 +    QCOMPARE(sizeof(QQmlInstruction::instr_storePointF::QPointF), sizeof(QPointF));
 +    QCOMPARE(Q_ALIGNOF(QQmlInstruction::instr_storePointF::QPointF), Q_ALIGNOF(QPointF));
 +
 +    QQmlInstruction i;
 +    i.storePointF.point.xp = 8.7;
 +    i.storePointF.point.yp = 11.3;
 +
 +    const QPointF &point = (const QPointF &)(i.storePointF.point);
 +    QCOMPARE(point.x(), 8.7);
 +    QCOMPARE(point.y(), 11.3);
 +}
 +
 +void tst_qqmlinstruction::size()
 +{
 +    QCOMPARE(sizeof(QQmlInstruction::instr_storeSize::QSize), sizeof(QSize));
 +    QCOMPARE(Q_ALIGNOF(QQmlInstruction::instr_storeSize::QSize), Q_ALIGNOF(QSize));
 +
 +    QQmlInstruction i;
 +    i.storeSize.size.wd = 8;
 +    i.storeSize.size.ht = 11;
 +
 +    const QSize &size = (const QSize &)(i.storeSize.size);
 +    QCOMPARE(size.width(), 8);
 +    QCOMPARE(size.height(), 11);
 +}
 +
 +void tst_qqmlinstruction::sizef()
 +{
 +    QCOMPARE(sizeof(QQmlInstruction::instr_storeSizeF::QSizeF), sizeof(QSizeF));
 +    QCOMPARE(Q_ALIGNOF(QQmlInstruction::instr_storeSizeF::QSizeF), Q_ALIGNOF(QSizeF));
 +
 +    QQmlInstruction i;
 +    i.storeSizeF.size.wd = 8;
 +    i.storeSizeF.size.ht = 11;
 +
 +    const QSizeF &size = (const QSizeF &)(i.storeSizeF.size);
 +    QCOMPARE(size.width(), (qreal)8);
 +    QCOMPARE(size.height(), (qreal)11);
 +}
 +
 +void tst_qqmlinstruction::rect()
 +{
 +    QCOMPARE(sizeof(QQmlInstruction::instr_storeRect::QRect), sizeof(QRect));
 +    QCOMPARE(Q_ALIGNOF(QQmlInstruction::instr_storeRect::QRect), Q_ALIGNOF(QRect));
 +
 +    QQmlInstruction i;
 +    i.storeRect.rect.x1 = 8;
 +    i.storeRect.rect.y1 = 11;
 +    i.storeRect.rect.x2 = 13;
 +    i.storeRect.rect.y2 = 19;
 +
 +    const QRect &rect = (const QRect &)(i.storeRect.rect);
 +    QCOMPARE(rect.left(), 8);
 +    QCOMPARE(rect.top(), 11);
 +    QCOMPARE(rect.right(), 13);
 +    QCOMPARE(rect.bottom(), 19);
 +}
 +
 +void tst_qqmlinstruction::rectf()
 +{
 +    QCOMPARE(sizeof(QQmlInstruction::instr_storeRectF::QRectF), sizeof(QRectF));
 +    QCOMPARE(Q_ALIGNOF(QQmlInstruction::instr_storeRectF::QRectF), Q_ALIGNOF(QRectF));
 +
 +    QQmlInstruction i;
 +    i.storeRectF.rect.xp = 8;
 +    i.storeRectF.rect.yp = 11;
 +    i.storeRectF.rect.w = 13;
 +    i.storeRectF.rect.h = 19;
 +
 +    const QRectF &rect = (const QRectF &)(i.storeRectF.rect);
 +    QCOMPARE(rect.left(), (qreal)8);
 +    QCOMPARE(rect.top(), (qreal)11);
 +    QCOMPARE(rect.width(), (qreal)13);
 +    QCOMPARE(rect.height(), (qreal)19);
 +}
 +
 +void tst_qqmlinstruction::vector3d()
 +{
 +    QCOMPARE(sizeof(QQmlInstruction::instr_storeVector3D::QVector3D), sizeof(QVector3D));
 +    QCOMPARE(Q_ALIGNOF(QQmlInstruction::instr_storeVector3D::QVector3D), Q_ALIGNOF(QVector3D));
 +
 +    QQmlInstruction i;
 +    i.storeVector3D.vector.xp = 8.2;
 +    i.storeVector3D.vector.yp = 99.3;
 +    i.storeVector3D.vector.zp = 12.0;
 +
 +    const QVector3D &vector = (const QVector3D &)(i.storeVector3D.vector);
 +    QCOMPARE(vector.x(), (qreal)(float)8.2);
 +    QCOMPARE(vector.y(), (qreal)(float)99.3);
 +    QCOMPARE(vector.z(), (qreal)(float)12.0);
 +}
 +
 +void tst_qqmlinstruction::vector4d()
 +{
 +    QCOMPARE(sizeof(QQmlInstruction::instr_storeVector4D::QVector4D), sizeof(QVector4D));
 +    QCOMPARE(Q_ALIGNOF(QQmlInstruction::instr_storeVector4D::QVector4D), Q_ALIGNOF(QVector4D));
 +
 +    QQmlInstruction i;
 +    i.storeVector4D.vector.xp = 8.2;
 +    i.storeVector4D.vector.yp = 99.3;
 +    i.storeVector4D.vector.zp = 12.0;
 +    i.storeVector4D.vector.wp = 121.1;
 +
 +    const QVector4D &vector = (const QVector4D &)(i.storeVector4D.vector);
 +    QCOMPARE(vector.x(), (qreal)(float)8.2);
 +    QCOMPARE(vector.y(), (qreal)(float)99.3);
 +    QCOMPARE(vector.z(), (qreal)(float)12.0);
 +    QCOMPARE(vector.w(), (qreal)(float)121.1);
 +}
 +
 +void tst_qqmlinstruction::time()
 +{
 +    QCOMPARE(sizeof(QQmlInstruction::instr_storeTime::QTime), sizeof(QTime));
 +    QCOMPARE(Q_ALIGNOF(QQmlInstruction::instr_storeTime::QTime), Q_ALIGNOF(QTime));
 +}
 +
 +QTEST_MAIN(tst_qqmlinstruction)
 +
 +#include "tst_qqmlinstruction.moc"
index e9898bd,0000000..e7294f0
mode 100644,000000..100644
--- /dev/null
@@@ -1,823 -1,0 +1,824 @@@
- Q_DECLARE_INTERFACE(MyInterface, "com.trolltech.Qt.Test.MyInterface");
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#ifndef TESTTYPES_H
 +#define TESTTYPES_H
 +
 +#include <QtCore/qobject.h>
 +#include <QtCore/qrect.h>
 +#include <QtCore/qdatetime.h>
 +#include <QtGui/qmatrix.h>
 +#include <QtGui/qcolor.h>
 +#include <QtGui/qvector3d.h>
 +#include <QtGui/qvector4d.h>
 +#include <QtQml/qqml.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtQml/qqmlparserstatus.h>
 +#include <QtQml/qqmlpropertyvaluesource.h>
 +#include <QtQml/qqmlscriptstring.h>
 +#include <QtQml/qqmlproperty.h>
 +
 +#include <private/qqmlcustomparser_p.h>
 +
 +QVariant myCustomVariantTypeConverter(const QString &data);
 +
 +class MyInterface 
 +{
 +public:
 +    MyInterface() : id(913) {}
 +    int id;
 +};
 +
 +QT_BEGIN_NAMESPACE
++#define MyInterface_iid "org.qt-project.Qt.Test.MyInterface"
++Q_DECLARE_INTERFACE(MyInterface, MyInterface_iid);
 +QT_END_NAMESPACE
 +QML_DECLARE_INTERFACE(MyInterface);
 +
 +struct MyCustomVariantType
 +{
 +    MyCustomVariantType() : a(0) {}
 +    int a;
 +};
 +Q_DECLARE_METATYPE(MyCustomVariantType);
 +
 +class MyAttachedObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
 +    Q_PROPERTY(int value2 READ value2 WRITE setValue2)
 +public:
 +    MyAttachedObject(QObject *parent) : QObject(parent), m_value(0), m_value2(0) {}
 +
 +    int value() const { return m_value; }
 +    void setValue(int v) { if (m_value != v) { m_value = v; emit valueChanged(); } }
 +
 +    int value2() const { return m_value2; }
 +    void setValue2(int v) { m_value2 = v; }
 +
 +signals:
 +    void valueChanged();
 +
 +private:
 +    int m_value;
 +    int m_value2;
 +};
 +
 +class MyQmlObject : public QObject, public MyInterface
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value WRITE setValue FINAL)
 +    Q_PROPERTY(QString readOnlyString READ readOnlyString)
 +    Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)
 +    Q_PROPERTY(QRect rect READ rect WRITE setRect)
 +    Q_PROPERTY(QMatrix matrix READ matrix WRITE setMatrix)  //assumed to be unsupported by QML
 +    Q_PROPERTY(MyInterface *interfaceProperty READ interface WRITE setInterface)
 +    Q_PROPERTY(int onLiteralSignal READ onLiteralSignal WRITE setOnLiteralSignal)
 +    Q_PROPERTY(MyCustomVariantType customType READ customType WRITE setCustomType)
 +    Q_PROPERTY(MyQmlObject *qmlobjectProperty READ qmlobject WRITE setQmlobject)
 +    Q_PROPERTY(int propertyWithNotify READ propertyWithNotify WRITE setPropertyWithNotify NOTIFY oddlyNamedNotifySignal)
 +    Q_PROPERTY(int nonScriptable READ nonScriptable WRITE setNonScriptable SCRIPTABLE false)
 +
 +    Q_INTERFACES(MyInterface)
 +public:
 +    MyQmlObject() : m_value(-1), m_interface(0), m_qmlobject(0) { qRegisterMetaType<MyCustomVariantType>("MyCustomVariantType"); }
 +
 +    int value() const { return m_value; }
 +    void setValue(int v) { m_value = v; }
 +
 +    QString readOnlyString() const { return QLatin1String(""); }
 +
 +    bool enabled() const { return false; }
 +    void setEnabled(bool) {}
 +
 +    QRect rect() const { return QRect(); }
 +    void setRect(const QRect&) {}
 +
 +    QMatrix matrix() const { return QMatrix(); }
 +    void setMatrix(const QMatrix&) {}
 +
 +    MyInterface *interface() const { return m_interface; }
 +    void setInterface(MyInterface *iface) { m_interface = iface; }
 +
 +    static MyAttachedObject *qmlAttachedProperties(QObject *other) {
 +        return new MyAttachedObject(other);
 +    }
 +    Q_CLASSINFO("DefaultMethod", "basicSlot()")
 +
 +    int onLiteralSignal() const { return m_value; }
 +    void setOnLiteralSignal(int v) { m_value = v; }
 +
 +    MyQmlObject *qmlobject() const { return m_qmlobject; }
 +    void setQmlobject(MyQmlObject *o) { m_qmlobject = o; }
 +
 +    MyCustomVariantType customType() const { return m_custom; }
 +    void setCustomType(const MyCustomVariantType &v)  { m_custom = v; }
 +
 +    int propertyWithNotify() const { return m_propertyWithNotify; }
 +    void setPropertyWithNotify(int i) { m_propertyWithNotify = i; emit oddlyNamedNotifySignal(); }
 +
 +    int nonScriptable() const { return 0; }
 +    void setNonScriptable(int) {}
 +public slots:
 +    void basicSlot() { qWarning("MyQmlObject::basicSlot"); }
 +    void basicSlotWithArgs(int v) { qWarning("MyQmlObject::basicSlotWithArgs(%d)", v); }
 +
 +signals:
 +    void basicSignal();
 +    void basicParameterizedSignal(int parameter);
 +    void oddlyNamedNotifySignal();
 +
 +private:
 +    friend class tst_qqmllanguage;
 +    int m_value;
 +    MyInterface *m_interface;
 +    MyQmlObject *m_qmlobject;
 +    MyCustomVariantType m_custom;
 +    int m_propertyWithNotify;
 +};
 +QML_DECLARE_TYPE(MyQmlObject)
 +QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES)
 +
 +class MyGroupedObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(QQmlScriptString script READ script WRITE setScript)
 +    Q_PROPERTY(int value READ value WRITE setValue)
 +public:
 +    QQmlScriptString script() const { return m_script; }
 +    void setScript(const QQmlScriptString &s) { m_script = s; }
 +
 +    int value() const { return m_value; }
 +    void setValue(int v) { m_value = v; }
 +
 +private:
 +    int m_value;
 +    QQmlScriptString m_script;
 +};
 +
 +
 +class MyTypeObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_ENUMS(MyEnum)
 +    Q_FLAGS(MyFlags)
 +
 +    Q_PROPERTY(QString id READ id WRITE setId)
 +    Q_PROPERTY(QObject *objectProperty READ objectProperty WRITE setObjectProperty)
 +    Q_PROPERTY(QQmlComponent *componentProperty READ componentProperty WRITE setComponentProperty)
 +    Q_PROPERTY(MyFlags flagProperty READ flagProperty WRITE setFlagProperty)
 +    Q_PROPERTY(MyEnum enumProperty READ enumProperty WRITE setEnumProperty)
 +    Q_PROPERTY(MyEnum readOnlyEnumProperty READ readOnlyEnumProperty)
 +    Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty)
 +    Q_PROPERTY(uint uintProperty READ uintProperty WRITE setUintProperty)
 +    Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty)
 +    Q_PROPERTY(qreal realProperty READ realProperty WRITE setRealProperty)
 +    Q_PROPERTY(double doubleProperty READ doubleProperty WRITE setDoubleProperty)
 +    Q_PROPERTY(float floatProperty READ floatProperty WRITE setFloatProperty)
 +    Q_PROPERTY(QColor colorProperty READ colorProperty WRITE setColorProperty)
 +    Q_PROPERTY(QDate dateProperty READ dateProperty WRITE setDateProperty)
 +    Q_PROPERTY(QTime timeProperty READ timeProperty WRITE setTimeProperty)
 +    Q_PROPERTY(QDateTime dateTimeProperty READ dateTimeProperty WRITE setDateTimeProperty)
 +    Q_PROPERTY(QPoint pointProperty READ pointProperty WRITE setPointProperty)
 +    Q_PROPERTY(QPointF pointFProperty READ pointFProperty WRITE setPointFProperty)
 +    Q_PROPERTY(QSize sizeProperty READ sizeProperty WRITE setSizeProperty)
 +    Q_PROPERTY(QSizeF sizeFProperty READ sizeFProperty WRITE setSizeFProperty)
 +    Q_PROPERTY(QRect rectProperty READ rectProperty WRITE setRectProperty NOTIFY rectPropertyChanged)
 +    Q_PROPERTY(QRect rectProperty2 READ rectProperty2 WRITE setRectProperty2)
 +    Q_PROPERTY(QRectF rectFProperty READ rectFProperty WRITE setRectFProperty)
 +    Q_PROPERTY(bool boolProperty READ boolProperty WRITE setBoolProperty)
 +    Q_PROPERTY(QVariant variantProperty READ variantProperty WRITE setVariantProperty)
 +    Q_PROPERTY(QVector3D vectorProperty READ vectorProperty WRITE setVectorProperty)
 +    Q_PROPERTY(QVector4D vector4Property READ vector4Property WRITE setVector4Property)
 +    Q_PROPERTY(QUrl urlProperty READ urlProperty WRITE setUrlProperty)
 +
 +    Q_PROPERTY(QQmlScriptString scriptProperty READ scriptProperty WRITE setScriptProperty)
 +    Q_PROPERTY(MyGroupedObject *grouped READ grouped CONSTANT)
 +    Q_PROPERTY(MyGroupedObject *nullGrouped READ nullGrouped CONSTANT)
 +
 +public:
 +    MyTypeObject()
 +        : objectPropertyValue(0), componentPropertyValue(0) {}
 +
 +    QString idValue;
 +    QString id() const {
 +        return idValue;
 +    }
 +    void setId(const QString &v) {
 +        idValue = v;
 +    }
 +
 +    QObject *objectPropertyValue;
 +    QObject *objectProperty() const {
 +        return objectPropertyValue;
 +    }
 +    void setObjectProperty(QObject *v) {
 +        objectPropertyValue = v;
 +    }
 +
 +    QQmlComponent *componentPropertyValue;
 +    QQmlComponent *componentProperty() const {
 +        return componentPropertyValue;
 +    }
 +    void setComponentProperty(QQmlComponent *v) {
 +        componentPropertyValue = v;
 +    }
 +
 +    enum MyFlag { FlagVal1 = 0x01, FlagVal2 = 0x02, FlagVal3 = 0x04 };
 +    Q_DECLARE_FLAGS(MyFlags, MyFlag)
 +    MyFlags flagPropertyValue;
 +    MyFlags flagProperty() const {
 +        return flagPropertyValue;
 +    }
 +    void setFlagProperty(MyFlags v) {
 +        flagPropertyValue = v;
 +    }
 +
 +    enum MyEnum { EnumVal1, EnumVal2 };
 +    MyEnum enumPropertyValue;
 +    MyEnum enumProperty() const {
 +        return enumPropertyValue;
 +    }
 +    void setEnumProperty(MyEnum v) {
 +        enumPropertyValue = v;
 +    }
 +
 +    MyEnum readOnlyEnumProperty() const {
 +        return EnumVal1;
 +    }
 +
 +    QString stringPropertyValue;
 +    QString stringProperty() const {
 +       return stringPropertyValue;
 +    }
 +    void setStringProperty(const QString &v) {
 +        stringPropertyValue = v;
 +    }
 +
 +    uint uintPropertyValue;
 +    uint uintProperty() const {
 +       return uintPropertyValue;
 +    }
 +    void setUintProperty(const uint &v) {
 +        uintPropertyValue = v;
 +    }
 +
 +    int intPropertyValue;
 +    int intProperty() const {
 +       return intPropertyValue;
 +    }
 +    void setIntProperty(const int &v) {
 +        intPropertyValue = v;
 +    }
 +
 +    qreal realPropertyValue;
 +    qreal realProperty() const {
 +       return realPropertyValue;
 +    }
 +    void setRealProperty(const qreal &v) {
 +        realPropertyValue = v;
 +    }
 +
 +    double doublePropertyValue;
 +    double doubleProperty() const {
 +       return doublePropertyValue;
 +    }
 +    void setDoubleProperty(const double &v) {
 +        doublePropertyValue = v;
 +    }
 +
 +    float floatPropertyValue;
 +    float floatProperty() const {
 +       return floatPropertyValue;
 +    }
 +    void setFloatProperty(const float &v) {
 +        floatPropertyValue = v;
 +    }
 +
 +    QColor colorPropertyValue;
 +    QColor colorProperty() const {
 +       return colorPropertyValue;
 +    }
 +    void setColorProperty(const QColor &v) {
 +        colorPropertyValue = v;
 +    }
 +
 +    QDate datePropertyValue;
 +    QDate dateProperty() const {
 +       return datePropertyValue;
 +    }
 +    void setDateProperty(const QDate &v) {
 +        datePropertyValue = v;
 +    }
 +
 +    QTime timePropertyValue;
 +    QTime timeProperty() const {
 +       return timePropertyValue;
 +    }
 +    void setTimeProperty(const QTime &v) {
 +        timePropertyValue = v;
 +    }
 +
 +    QDateTime dateTimePropertyValue;
 +    QDateTime dateTimeProperty() const {
 +       return dateTimePropertyValue;
 +    }
 +    void setDateTimeProperty(const QDateTime &v) {
 +        dateTimePropertyValue = v;
 +    }
 +
 +    QPoint pointPropertyValue;
 +    QPoint pointProperty() const {
 +       return pointPropertyValue;
 +    }
 +    void setPointProperty(const QPoint &v) {
 +        pointPropertyValue = v;
 +    }
 +
 +    QPointF pointFPropertyValue;
 +    QPointF pointFProperty() const {
 +       return pointFPropertyValue;
 +    }
 +    void setPointFProperty(const QPointF &v) {
 +        pointFPropertyValue = v;
 +    }
 +
 +    QSize sizePropertyValue;
 +    QSize sizeProperty() const {
 +       return sizePropertyValue;
 +    }
 +    void setSizeProperty(const QSize &v) {
 +        sizePropertyValue = v;
 +    }
 +
 +    QSizeF sizeFPropertyValue;
 +    QSizeF sizeFProperty() const {
 +       return sizeFPropertyValue;
 +    }
 +    void setSizeFProperty(const QSizeF &v) {
 +        sizeFPropertyValue = v;
 +    }
 +
 +    QRect rectPropertyValue;
 +    QRect rectProperty() const {
 +       return rectPropertyValue;
 +    }
 +    void setRectProperty(const QRect &v) {
 +        rectPropertyValue = v;
 +        emit rectPropertyChanged();
 +    }
 +
 +    QRect rectPropertyValue2;
 +    QRect rectProperty2() const {
 +       return rectPropertyValue2;
 +    }
 +    void setRectProperty2(const QRect &v) {
 +        rectPropertyValue2 = v;
 +    }
 +
 +    QRectF rectFPropertyValue;
 +    QRectF rectFProperty() const {
 +       return rectFPropertyValue;
 +    }
 +    void setRectFProperty(const QRectF &v) {
 +        rectFPropertyValue = v;
 +    }
 +
 +    bool boolPropertyValue;
 +    bool boolProperty() const {
 +       return boolPropertyValue;
 +    }
 +    void setBoolProperty(const bool &v) {
 +        boolPropertyValue = v;
 +    }
 +
 +    QVariant variantPropertyValue;
 +    QVariant variantProperty() const {
 +       return variantPropertyValue;
 +    }
 +    void setVariantProperty(const QVariant &v) {
 +        variantPropertyValue = v;
 +    }
 +
 +    QVector3D vectorPropertyValue;
 +    QVector3D vectorProperty() const {
 +        return vectorPropertyValue;
 +    }
 +    void setVectorProperty(const QVector3D &v) {
 +        vectorPropertyValue = v;
 +    }
 +
 +    QVector4D vector4PropertyValue;
 +    QVector4D vector4Property() const {
 +        return vector4PropertyValue;
 +    }
 +    void setVector4Property(const QVector4D &v) {
 +        vector4PropertyValue = v;
 +    }
 +
 +    QUrl urlPropertyValue;
 +    QUrl urlProperty() const {
 +        return urlPropertyValue;
 +    }
 +    void setUrlProperty(const QUrl &v) {
 +        urlPropertyValue = v;
 +    }
 +
 +    QQmlScriptString scriptPropertyValue;
 +    QQmlScriptString scriptProperty() const {
 +        return scriptPropertyValue;
 +    }
 +    void setScriptProperty(const QQmlScriptString &v) {
 +        scriptPropertyValue = v;
 +    }
 +
 +    MyGroupedObject groupedValue;
 +    MyGroupedObject *grouped() { return &groupedValue; }
 +
 +    MyGroupedObject *nullGrouped() { return 0; }
 +
 +    void doAction() { emit action(); }
 +signals:
 +    void action();
 +    void rectPropertyChanged();
 +};
 +Q_DECLARE_OPERATORS_FOR_FLAGS(MyTypeObject::MyFlags)
 +
 +
 +class MyContainer : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(QQmlListProperty<QObject> children READ children)
 +    Q_PROPERTY(QQmlListProperty<MyContainer> containerChildren READ containerChildren)
 +    Q_PROPERTY(QQmlListProperty<MyInterface> qlistInterfaces READ qlistInterfaces)
 +    Q_CLASSINFO("DefaultProperty", "children")
 +public:
 +    MyContainer() {}
 +
 +    QQmlListProperty<QObject> children() { return QQmlListProperty<QObject>(this, m_children); }
 +    QQmlListProperty<MyContainer> containerChildren() { return QQmlListProperty<MyContainer>(this, m_containerChildren); }
 +    QList<QObject *> *getChildren() { return &m_children; }
 +    QQmlListProperty<MyInterface> qlistInterfaces() { return QQmlListProperty<MyInterface>(this, m_interfaces); }
 +    QList<MyInterface *> *getQListInterfaces() { return &m_interfaces; }
 +
 +    QList<MyContainer*> m_containerChildren;
 +    QList<QObject*> m_children;
 +    QList<MyInterface *> m_interfaces;
 +};
 +
 +
 +class MyPropertyValueSource : public QObject, public QQmlPropertyValueSource
 +{
 +    Q_OBJECT
 +    Q_INTERFACES(QQmlPropertyValueSource)
 +public:
 +    MyPropertyValueSource()
 +        : QQmlPropertyValueSource() {}
 +
 +    QQmlProperty prop;
 +    virtual void setTarget(const QQmlProperty &p)
 +    {
 +        prop = p;
 +    }
 +};
 +
 +class UnavailableType : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    UnavailableType() {}
 +};
 +
 +class MyDotPropertyObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(MyQmlObject *obj READ obj)
 +    Q_PROPERTY(MyQmlObject *readWriteObj READ readWriteObj WRITE setReadWriteObj)
 +public:
 +    MyDotPropertyObject() : m_rwobj(0), m_ownRWObj(false) {}
 +    ~MyDotPropertyObject()
 +    {
 +        if (m_ownRWObj)
 +            delete m_rwobj;
 +    }
 +
 +    MyQmlObject *obj() { return 0; }
 +
 +    MyQmlObject *readWriteObj()
 +    {
 +        if (!m_rwobj) {
 +            m_rwobj = new MyQmlObject;
 +            m_ownRWObj = true;
 +        }
 +        return m_rwobj;
 +    }
 +
 +    void setReadWriteObj(MyQmlObject *obj)
 +    {
 +        if (m_ownRWObj) {
 +            delete m_rwobj;
 +            m_ownRWObj = false;
 +        }
 +
 +        m_rwobj = obj;
 +    }
 +
 +private:
 +    MyQmlObject *m_rwobj;
 +    bool m_ownRWObj;
 +};
 +
 +
 +namespace MyNamespace {
 +    class MyNamespacedType : public QObject
 +    {
 +        Q_OBJECT
 +    };
 +
 +    class MySecondNamespacedType : public QObject
 +    {
 +        Q_OBJECT
 +        Q_PROPERTY(QQmlListProperty<MyNamespace::MyNamespacedType> list READ list)
 +    public:
 +        QQmlListProperty<MyNamespacedType> list() { return QQmlListProperty<MyNamespacedType>(this, m_list); }
 +
 +    private:
 +        QList<MyNamespacedType *> m_list;
 +    };
 +}
 +
 +class MyCustomParserType : public QObject
 +{
 +    Q_OBJECT
 +};
 +
 +class MyCustomParserTypeParser : public QQmlCustomParser
 +{
 +public:
 +    QByteArray compile(const QList<QQmlCustomParserProperty> &) { return QByteArray(); }
 +    void setCustomData(QObject *, const QByteArray &) {}
 +};
 +
 +class MyParserStatus : public QObject, public QQmlParserStatus
 +{
 +    Q_INTERFACES(QQmlParserStatus)
 +    Q_OBJECT
 +public:
 +    MyParserStatus() : m_cbc(0), m_ccc(0) {}
 +
 +    int classBeginCount() const { return m_cbc; }
 +    int componentCompleteCount() const { return m_ccc; }
 +
 +    virtual void classBegin() { m_cbc++; }
 +    virtual void componentComplete() { m_ccc++; }
 +private:
 +    int m_cbc;
 +    int m_ccc;
 +};
 +
 +class MyRevisionedBaseClassRegistered : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(qreal propA READ propA WRITE setPropA NOTIFY propAChanged)
 +    Q_PROPERTY(qreal propB READ propB WRITE setPropB NOTIFY propBChanged REVISION 1)
 +
 +public:
 +    MyRevisionedBaseClassRegistered() : m_pa(1), m_pb(2) {}
 +
 +    qreal propA() const { return m_pa; }
 +    void setPropA(qreal p) {
 +        if (p != m_pa) {
 +            m_pa = p;
 +            emit propAChanged();
 +        }
 +    }
 +    qreal propB() const { return m_pb; }
 +    void setPropB(qreal p) {
 +        if (p != m_pb) {
 +            m_pb = p;
 +            emit propBChanged();
 +        }
 +    }
 +
 +    Q_INVOKABLE void methodA() { }
 +    Q_INVOKABLE Q_REVISION(1) void methodB() { }
 +
 +signals:
 +    void propAChanged();
 +    void propBChanged();
 +
 +    void signalA();
 +    Q_REVISION(1) void signalB();
 +
 +protected:
 +    qreal m_pa;
 +    qreal m_pb;
 +};
 +
 +class MyRevisionedIllegalOverload : public MyRevisionedBaseClassRegistered
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(qreal propA READ propA WRITE setPropA REVISION 1);
 +};
 +
 +class MyRevisionedLegalOverload : public MyRevisionedBaseClassRegistered
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(qreal propB READ propB WRITE setPropB REVISION 1);
 +};
 +
 +class MyRevisionedBaseClassUnregistered : public MyRevisionedBaseClassRegistered
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(qreal propC READ propC WRITE setPropC NOTIFY propCChanged)
 +    Q_PROPERTY(qreal propD READ propD WRITE setPropD NOTIFY propDChanged REVISION 1)
 +
 +public:
 +    MyRevisionedBaseClassUnregistered() : m_pc(1), m_pd(2) {}
 +
 +    qreal propC() const { return m_pc; }
 +    void setPropC(qreal p) {
 +        if (p != m_pc) {
 +            m_pc = p;
 +            emit propCChanged();
 +        }
 +    }
 +    qreal propD() const { return m_pd; }
 +    void setPropD(qreal p) {
 +        if (p != m_pd) {
 +            m_pd = p;
 +            emit propDChanged();
 +        }
 +    }
 +
 +    Q_INVOKABLE void methodC() { }
 +    Q_INVOKABLE Q_REVISION(1) void methodD() { }
 +
 +signals:
 +    void propCChanged();
 +    void propDChanged();
 +
 +    void signalC();
 +    Q_REVISION(1) void signalD();
 +
 +protected:
 +    qreal m_pc;
 +    qreal m_pd;
 +};
 +
 +class MyRevisionedClass : public MyRevisionedBaseClassUnregistered
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(qreal prop1 READ prop1 WRITE setProp1 NOTIFY prop1Changed)
 +    Q_PROPERTY(qreal prop2 READ prop2 WRITE setProp2 NOTIFY prop2Changed REVISION 1)
 +
 +public:
 +    MyRevisionedClass() : m_p1(1), m_p2(2) {}
 +
 +    qreal prop1() const { return m_p1; }
 +    void setProp1(qreal p) {
 +        if (p != m_p1) {
 +            m_p1 = p;
 +            emit prop1Changed();
 +        }
 +    }
 +    qreal prop2() const { return m_p2; }
 +    void setProp2(qreal p) {
 +        if (p != m_p2) {
 +            m_p2 = p;
 +            emit prop2Changed();
 +        }
 +    }
 +
 +    Q_INVOKABLE void method1() { }
 +    Q_INVOKABLE Q_REVISION(1) void method2() { }
 +
 +signals:
 +    void prop1Changed();
 +    void prop2Changed();
 +
 +    void signal1();
 +    Q_REVISION(1) void signal2();
 +
 +protected:
 +    qreal m_p1;
 +    qreal m_p2;
 +};
 +
 +class MyRevisionedSubclass : public MyRevisionedClass
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(qreal prop3 READ prop3 WRITE setProp3 NOTIFY prop3Changed)
 +    Q_PROPERTY(qreal prop4 READ prop4 WRITE setProp4 NOTIFY prop4Changed REVISION 1)
 +
 +public:
 +    MyRevisionedSubclass() : m_p3(3), m_p4(4) {}
 +
 +    qreal prop3() const { return m_p3; }
 +    void setProp3(qreal p) {
 +        if (p != m_p3) {
 +            m_p3 = p;
 +            emit prop3Changed();
 +        }
 +    }
 +    qreal prop4() const { return m_p4; }
 +    void setProp4(qreal p) {
 +        if (p != m_p4) {
 +            m_p4 = p;
 +            emit prop4Changed();
 +        }
 +    }
 +
 +    Q_INVOKABLE void method3() { }
 +    Q_INVOKABLE Q_REVISION(1) void method4() { }
 +
 +signals:
 +    void prop3Changed();
 +    void prop4Changed();
 +
 +    void signal3();
 +    Q_REVISION(1) void signal4();
 +
 +protected:
 +    qreal m_p3;
 +    qreal m_p4;
 +};
 +
 +class MySubclass : public MyRevisionedClass
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(qreal prop5 READ prop5 WRITE setProp5 NOTIFY prop5Changed)
 +
 +public:
 +    MySubclass() : m_p5(5) {}
 +
 +    qreal prop5() const { return m_p5; }
 +    void setProp5(qreal p) {
 +        if (p != m_p5) {
 +            m_p5 = p;
 +            emit prop5Changed();
 +        }
 +    }
 +
 +    Q_INVOKABLE void method5() { }
 +
 +signals:
 +    void prop5Changed();
 +
 +protected:
 +    qreal m_p5;
 +};
 +
 +class MyVersion2Class : public QObject
 +{
 +    Q_OBJECT
 +};
 +
 +QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered)
 +QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered)
 +QML_DECLARE_TYPE(MyRevisionedClass)
 +QML_DECLARE_TYPE(MyRevisionedSubclass)
 +QML_DECLARE_TYPE(MySubclass)
 +
 +
 +
 +void registerTypes();
 +
 +#endif // TESTTYPES_H
index 379c32d,0000000..266cd2a
mode 100644,000000..100644
--- /dev/null
@@@ -1,2289 -1,0 +1,2290 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <qtest.h>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtCore/qcoreapplication.h>
 +#include <QtCore/qfile.h>
 +#include <QtCore/qdebug.h>
 +#include <QtCore/qfileinfo.h>
 +#include <QtCore/qdir.h>
 +
 +#include <private/qqmlproperty_p.h>
 +#include <private/qqmlmetatype_p.h>
 +#include <private/qqmlglobal_p.h>
 +
 +#include "testtypes.h"
 +#include "testhttpserver.h"
 +
 +DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES)
 +
 +/*
 +    Returns the path to some testdata file or directory.
 +*/
 +QString testdata(QString const& name = QString())
 +{
 +    static const QString dataDirectory = QDir::currentPath() + QLatin1String("/data");
 +    QString result = dataDirectory;
 +    if (!name.isEmpty()) {
 +        result += QLatin1Char('/');
 +        result += name;
 +    }
 +    return result;
 +}
 +
 +/*
 +This test case covers QML language issues.  This covers everything that does not
 +involve evaluating ECMAScript expressions and bindings.
 +
 +Evaluation of expressions and bindings is covered in qmlecmascript
 +*/
 +class tst_qqmllanguage : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    tst_qqmllanguage() {
 +        QQmlMetaType::registerCustomStringConverter(qMetaTypeId<MyCustomVariantType>(), myCustomVariantTypeConverter);
 +        engine.addImportPath(testdata("lib"));
 +    }
 +
 +private slots:
 +    void initTestCase();
 +    void cleanupTestCase();
 +
 +    void errors_data();
 +    void errors();
 +
 +    void insertedSemicolon_data();
 +    void insertedSemicolon();
 +
 +    void simpleObject();
 +    void simpleContainer();
 +    void interfaceProperty();
 +    void interfaceQList();
 +    void assignObjectToSignal();
 +    void assignObjectToVariant();
 +    void assignLiteralSignalProperty();
 +    void assignQmlComponent();
 +    void assignBasicTypes();
 +    void assignTypeExtremes();
 +    void assignCompositeToType();
 +    void assignLiteralToVariant();
 +    void assignLiteralToVar();
 +    void customParserTypes();
 +    void rootAsQmlComponent();
 +    void inlineQmlComponents();
 +    void idProperty();
 +    void autoNotifyConnection();
 +    void assignSignal();
 +    void dynamicProperties();
 +    void dynamicPropertiesNested();
 +    void listProperties();
 +    void dynamicObjectProperties();
 +    void dynamicSignalsAndSlots();
 +    void simpleBindings();
 +    void autoComponentCreation();
 +    void propertyValueSource();
 +    void attachedProperties();
 +    void dynamicObjects();
 +    void customVariantTypes();
 +    void valueTypes();
 +    void cppnamespace();
 +    void aliasProperties();
 +    void aliasPropertiesAndSignals();
 +    void aliasPropertyChangeSignals();
 +    void componentCompositeType();
 +    void i18n();
 +    void i18n_data();
 +    void onCompleted();
 +    void onDestruction();
 +    void scriptString();
 +    void defaultPropertyListOrder();
 +    void declaredPropertyValues();
 +    void dontDoubleCallClassBegin();
 +    void reservedWords_data();
 +    void reservedWords();
 +    void inlineAssignmentsOverrideBindings();
 +    void nestedComponentRoots();
 +    void registrationOrder();
 +    void readonly();
 +
 +    void basicRemote_data();
 +    void basicRemote();
 +    void importsBuiltin_data();
 +    void importsBuiltin();
 +    void importsLocal_data();
 +    void importsLocal();
 +    void importsRemote_data();
 +    void importsRemote();
 +    void importsInstalled_data();
 +    void importsInstalled();
 +    void importsOrder_data();
 +    void importsOrder();
 +    void importIncorrectCase();
 +    void importJs_data();
 +    void importJs();
 +
 +    void qmlAttachedPropertiesObjectMethod();
 +    void customOnProperty();
 +    void variantNotify();
 +
 +    void revisions();
 +    void revisionOverloads();
 +
 +    void propertyInit();
 +    void remoteLoadCrash();
 +
 +    // regression tests for crashes
 +    void crash1();
 +    void crash2();
 +
 +private:
 +    QQmlEngine engine;
 +    void testType(const QString& qml, const QString& type, const QString& error);
 +};
 +
 +#define DETERMINE_ERRORS(errorfile,expected,actual)\
 +    QList<QByteArray> expected; \
 +    QList<QByteArray> actual; \
 +    do { \
 +        QFile file(testdata(QLatin1String(errorfile))); \
 +        QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); \
 +        QByteArray data = file.readAll(); \
 +        file.close(); \
 +        expected = data.split('\n'); \
 +        expected.removeAll(QByteArray("")); \
 +        QList<QQmlError> errors = component.errors(); \
 +        for (int ii = 0; ii < errors.count(); ++ii) { \
 +            const QQmlError &error = errors.at(ii); \
 +            QByteArray errorStr = QByteArray::number(error.line()) + ":" +  \
 +                                  QByteArray::number(error.column()) + ":" + \
 +                                  error.description().toUtf8(); \
 +            actual << errorStr; \
 +        } \
 +    } while (false);
 +
 +#define VERIFY_ERRORS(errorfile) \
 +    if (!errorfile) { \
 +        if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \
 +            qWarning() << "Unexpected Errors:" << component.errors(); \
 +        QVERIFY(!component.isError()); \
 +        QVERIFY(component.errors().isEmpty()); \
 +    } else { \
 +        DETERMINE_ERRORS(errorfile,actual,expected);\
 +        if (qgetenv("DEBUG") != "" && expected != actual) \
 +            qWarning() << "Expected:" << expected << "Actual:" << actual;  \
 +        if (qgetenv("QDECLARATIVELANGUAGE_UPDATEERRORS") != "" && expected != actual) {\
 +            QFile file(QLatin1String("data/") + QLatin1String(errorfile)); \
 +            QVERIFY(file.open(QIODevice::WriteOnly)); \
 +            for (int ii = 0; ii < actual.count(); ++ii) { \
 +                file.write(actual.at(ii)); file.write("\n"); \
 +            } \
 +            file.close(); \
 +        } else { \
 +            QCOMPARE(expected, actual); \
 +        } \
 +    }
 +
 +inline QUrl TEST_FILE(const QString &filename)
 +{
 +    return QUrl::fromLocalFile(testdata(filename));
 +}
 +
 +inline QUrl TEST_FILE(const char *filename)
 +{
 +    return TEST_FILE(QLatin1String(filename));
 +}
 +
 +void tst_qqmllanguage::cleanupTestCase()
 +{
 +    QVERIFY(QFile::remove(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile()));
 +}
 +
 +void tst_qqmllanguage::insertedSemicolon_data()
 +{
 +    QTest::addColumn<QString>("file");
 +    QTest::addColumn<QString>("errorFile");
 +    QTest::addColumn<bool>("create");
 +
 +    QTest::newRow("insertedSemicolon.1") << "insertedSemicolon.1.qml" << "insertedSemicolon.1.errors.txt" << false;
 +}
 +
 +void tst_qqmllanguage::insertedSemicolon()
 +{
 +    QFETCH(QString, file);
 +    QFETCH(QString, errorFile);
 +    QFETCH(bool, create);
 +
 +    QQmlComponent component(&engine, TEST_FILE(file));
 +
 +    if(create) {
 +        QObject *object = component.create();
 +        QVERIFY(object == 0);
 +    }
 +
 +    VERIFY_ERRORS(errorFile.toLatin1().constData());
 +}
 +
 +void tst_qqmllanguage::errors_data()
 +{
 +    QTest::addColumn<QString>("file");
 +    QTest::addColumn<QString>("errorFile");
 +    QTest::addColumn<bool>("create");
 +
 +    QTest::newRow("nonexistantProperty.1") << "nonexistantProperty.1.qml" << "nonexistantProperty.1.errors.txt" << false;
 +    QTest::newRow("nonexistantProperty.2") << "nonexistantProperty.2.qml" << "nonexistantProperty.2.errors.txt" << false;
 +    QTest::newRow("nonexistantProperty.3") << "nonexistantProperty.3.qml" << "nonexistantProperty.3.errors.txt" << false;
 +    QTest::newRow("nonexistantProperty.4") << "nonexistantProperty.4.qml" << "nonexistantProperty.4.errors.txt" << false;
 +    QTest::newRow("nonexistantProperty.5") << "nonexistantProperty.5.qml" << "nonexistantProperty.5.errors.txt" << false;
 +    QTest::newRow("nonexistantProperty.6") << "nonexistantProperty.6.qml" << "nonexistantProperty.6.errors.txt" << false;
 +
 +    QTest::newRow("wrongType (string for int)") << "wrongType.1.qml" << "wrongType.1.errors.txt" << false;
 +    QTest::newRow("wrongType (int for bool)") << "wrongType.2.qml" << "wrongType.2.errors.txt" << false;
 +    QTest::newRow("wrongType (bad rect)") << "wrongType.3.qml" << "wrongType.3.errors.txt" << false;
 +
 +    QTest::newRow("wrongType (invalid enum)") << "wrongType.4.qml" << "wrongType.4.errors.txt" << false;
 +    QTest::newRow("wrongType (int for uint)") << "wrongType.5.qml" << "wrongType.5.errors.txt" << false;
 +    QTest::newRow("wrongType (string for real)") << "wrongType.6.qml" << "wrongType.6.errors.txt" << false;
 +    QTest::newRow("wrongType (int for color)") << "wrongType.7.qml" << "wrongType.7.errors.txt" << false;
 +    QTest::newRow("wrongType (int for date)") << "wrongType.8.qml" << "wrongType.8.errors.txt" << false;
 +    QTest::newRow("wrongType (int for time)") << "wrongType.9.qml" << "wrongType.9.errors.txt" << false;
 +    QTest::newRow("wrongType (int for datetime)") << "wrongType.10.qml" << "wrongType.10.errors.txt" << false;
 +    QTest::newRow("wrongType (string for point)") << "wrongType.11.qml" << "wrongType.11.errors.txt" << false;
 +    QTest::newRow("wrongType (color for size)") << "wrongType.12.qml" << "wrongType.12.errors.txt" << false;
 +    QTest::newRow("wrongType (number string for int)") << "wrongType.13.qml" << "wrongType.13.errors.txt" << false;
 +    QTest::newRow("wrongType (int for string)") << "wrongType.14.qml" << "wrongType.14.errors.txt" << false;
 +    QTest::newRow("wrongType (int for url)") << "wrongType.15.qml" << "wrongType.15.errors.txt" << false;
 +    QTest::newRow("wrongType (invalid object)") << "wrongType.16.qml" << "wrongType.16.errors.txt" << false;
 +    QTest::newRow("wrongType (int for enum)") << "wrongType.17.qml" << "wrongType.17.errors.txt" << false;
 +
 +    QTest::newRow("readOnly.1") << "readOnly.1.qml" << "readOnly.1.errors.txt" << false;
 +    QTest::newRow("readOnly.2") << "readOnly.2.qml" << "readOnly.2.errors.txt" << false;
 +    QTest::newRow("readOnly.3") << "readOnly.3.qml" << "readOnly.3.errors.txt" << false;
 +    QTest::newRow("readOnly.4") << "readOnly.4.qml" << "readOnly.4.errors.txt" << false;
 +    QTest::newRow("readOnly.5") << "readOnly.5.qml" << "readOnly.5.errors.txt" << false;
 +
 +    QTest::newRow("listAssignment.1") << "listAssignment.1.qml" << "listAssignment.1.errors.txt" << false;
 +    QTest::newRow("listAssignment.2") << "listAssignment.2.qml" << "listAssignment.2.errors.txt" << false;
 +    QTest::newRow("listAssignment.3") << "listAssignment.3.qml" << "listAssignment.3.errors.txt" << false;
 +
 +    QTest::newRow("invalidID.1") << "invalidID.qml" << "invalidID.errors.txt" << false;
 +    QTest::newRow("invalidID.2") << "invalidID.2.qml" << "invalidID.2.errors.txt" << false;
 +    QTest::newRow("invalidID.3") << "invalidID.3.qml" << "invalidID.3.errors.txt" << false;
 +    QTest::newRow("invalidID.4") << "invalidID.4.qml" << "invalidID.4.errors.txt" << false;
 +    QTest::newRow("invalidID.5") << "invalidID.5.qml" << "invalidID.5.errors.txt" << false;
 +    QTest::newRow("invalidID.6") << "invalidID.6.qml" << "invalidID.6.errors.txt" << false;
 +    QTest::newRow("invalidID.7") << "invalidID.7.qml" << "invalidID.7.errors.txt" << false;
 +    QTest::newRow("invalidID.8") << "invalidID.8.qml" << "invalidID.8.errors.txt" << false;
 +    QTest::newRow("invalidID.9") << "invalidID.9.qml" << "invalidID.9.errors.txt" << false;
 +
 +    QTest::newRow("scriptString.1") << "scriptString.1.qml" << "scriptString.1.errors.txt" << false;
 +    QTest::newRow("scriptString.2") << "scriptString.2.qml" << "scriptString.2.errors.txt" << false;
 +
 +    QTest::newRow("unsupportedProperty") << "unsupportedProperty.qml" << "unsupportedProperty.errors.txt" << false;
 +    QTest::newRow("nullDotProperty") << "nullDotProperty.qml" << "nullDotProperty.errors.txt" << true;
 +    QTest::newRow("fakeDotProperty") << "fakeDotProperty.qml" << "fakeDotProperty.errors.txt" << false;
 +    QTest::newRow("duplicateIDs") << "duplicateIDs.qml" << "duplicateIDs.errors.txt" << false;
 +    QTest::newRow("unregisteredObject") << "unregisteredObject.qml" << "unregisteredObject.errors.txt" << false;
 +    QTest::newRow("empty") << "empty.qml" << "empty.errors.txt" << false;
 +    QTest::newRow("missingObject") << "missingObject.qml" << "missingObject.errors.txt" << false;
 +    QTest::newRow("failingComponent") << "failingComponentTest.qml" << "failingComponent.errors.txt" << false;
 +    QTest::newRow("missingSignal") << "missingSignal.qml" << "missingSignal.errors.txt" << false;
 +    QTest::newRow("finalOverride") << "finalOverride.qml" << "finalOverride.errors.txt" << false;
 +    QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false;
 +
 +    QTest::newRow("invalidGroupedProperty.1") << "invalidGroupedProperty.1.qml" << "invalidGroupedProperty.1.errors.txt" << false;
 +    QTest::newRow("invalidGroupedProperty.2") << "invalidGroupedProperty.2.qml" << "invalidGroupedProperty.2.errors.txt" << false;
 +    QTest::newRow("invalidGroupedProperty.3") << "invalidGroupedProperty.3.qml" << "invalidGroupedProperty.3.errors.txt" << false;
 +    QTest::newRow("invalidGroupedProperty.4") << "invalidGroupedProperty.4.qml" << "invalidGroupedProperty.4.errors.txt" << false;
 +    QTest::newRow("invalidGroupedProperty.5") << "invalidGroupedProperty.5.qml" << "invalidGroupedProperty.5.errors.txt" << false;
 +    QTest::newRow("invalidGroupedProperty.6") << "invalidGroupedProperty.6.qml" << "invalidGroupedProperty.6.errors.txt" << false;
 +    QTest::newRow("invalidGroupedProperty.7") << "invalidGroupedProperty.7.qml" << "invalidGroupedProperty.7.errors.txt" << true;
 +    QTest::newRow("invalidGroupedProperty.8") << "invalidGroupedProperty.8.qml" << "invalidGroupedProperty.8.errors.txt" << false;
 +    QTest::newRow("invalidGroupedProperty.9") << "invalidGroupedProperty.9.qml" << "invalidGroupedProperty.9.errors.txt" << false;
 +    QTest::newRow("invalidGroupedProperty.10") << "invalidGroupedProperty.10.qml" << "invalidGroupedProperty.10.errors.txt" << false;
 +
 +    QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false;
 +    QTest::newRow("importVersionMissing (builtin)") << "importVersionMissingBuiltIn.qml" << "importVersionMissingBuiltIn.errors.txt" << false;
 +    QTest::newRow("importVersionMissing (installed)") << "importVersionMissingInstalled.qml" << "importVersionMissingInstalled.errors.txt" << false;
 +    QTest::newRow("importNonExist (installed)") << "importNonExist.qml" << "importNonExist.errors.txt" << false;
 +    QTest::newRow("importNonExistOlder (installed)") << "importNonExistOlder.qml" << "importNonExistOlder.errors.txt" << false;
 +    QTest::newRow("importNewerVersion (installed)") << "importNewerVersion.qml" << "importNewerVersion.errors.txt" << false;
 +    QTest::newRow("invalidImportID") << "invalidImportID.qml" << "invalidImportID.errors.txt" << false;
 +    QTest::newRow("importFile") << "importFile.qml" << "importFile.errors.txt" << false;
 +
 +    QTest::newRow("signal.1") << "signal.1.qml" << "signal.1.errors.txt" << false;
 +    QTest::newRow("signal.2") << "signal.2.qml" << "signal.2.errors.txt" << false;
 +    QTest::newRow("signal.3") << "signal.3.qml" << "signal.3.errors.txt" << false;
 +    QTest::newRow("signal.4") << "signal.4.qml" << "signal.4.errors.txt" << false;
++    QTest::newRow("signal.5") << "signal.5.qml" << "signal.5.errors.txt" << false;
 +
 +    QTest::newRow("method.1") << "method.1.qml" << "method.1.errors.txt" << false;
 +
 +    QTest::newRow("property.1") << "property.1.qml" << "property.1.errors.txt" << false;
 +    QTest::newRow("property.2") << "property.2.qml" << "property.2.errors.txt" << false;
 +    QTest::newRow("property.3") << "property.3.qml" << "property.3.errors.txt" << false;
 +    QTest::newRow("property.4") << "property.4.qml" << "property.4.errors.txt" << false;
 +    QTest::newRow("property.6") << "property.6.qml" << "property.6.errors.txt" << false;
 +    QTest::newRow("property.7") << "property.7.qml" << "property.7.errors.txt" << false;
 +
 +    QTest::newRow("importScript.1") << "importscript.1.qml" << "importscript.1.errors.txt" << false;
 +
 +    QTest::newRow("Component.1") << "component.1.qml" << "component.1.errors.txt" << false;
 +    QTest::newRow("Component.2") << "component.2.qml" << "component.2.errors.txt" << false;
 +    QTest::newRow("Component.3") << "component.3.qml" << "component.3.errors.txt" << false;
 +    QTest::newRow("Component.4") << "component.4.qml" << "component.4.errors.txt" << false;
 +    QTest::newRow("Component.5") << "component.5.qml" << "component.5.errors.txt" << false;
 +    QTest::newRow("Component.6") << "component.6.qml" << "component.6.errors.txt" << false;
 +    QTest::newRow("Component.7") << "component.7.qml" << "component.7.errors.txt" << false;
 +    QTest::newRow("Component.8") << "component.8.qml" << "component.8.errors.txt" << false;
 +    QTest::newRow("Component.9") << "component.9.qml" << "component.9.errors.txt" << false;
 +
 +    QTest::newRow("MultiSet.1") << "multiSet.1.qml" << "multiSet.1.errors.txt" << false;
 +    QTest::newRow("MultiSet.2") << "multiSet.2.qml" << "multiSet.2.errors.txt" << false;
 +    QTest::newRow("MultiSet.3") << "multiSet.3.qml" << "multiSet.3.errors.txt" << false;
 +    QTest::newRow("MultiSet.4") << "multiSet.4.qml" << "multiSet.4.errors.txt" << false;
 +    QTest::newRow("MultiSet.5") << "multiSet.5.qml" << "multiSet.5.errors.txt" << false;
 +    QTest::newRow("MultiSet.6") << "multiSet.6.qml" << "multiSet.6.errors.txt" << false;
 +    QTest::newRow("MultiSet.7") << "multiSet.7.qml" << "multiSet.7.errors.txt" << false;
 +    QTest::newRow("MultiSet.8") << "multiSet.8.qml" << "multiSet.8.errors.txt" << false;
 +    QTest::newRow("MultiSet.9") << "multiSet.9.qml" << "multiSet.9.errors.txt" << false;
 +    QTest::newRow("MultiSet.10") << "multiSet.10.qml" << "multiSet.10.errors.txt" << false;
 +    QTest::newRow("MultiSet.11") << "multiSet.11.qml" << "multiSet.11.errors.txt" << false;
 +
 +    QTest::newRow("dynamicMeta.1") << "dynamicMeta.1.qml" << "dynamicMeta.1.errors.txt" << false;
 +    QTest::newRow("dynamicMeta.2") << "dynamicMeta.2.qml" << "dynamicMeta.2.errors.txt" << false;
 +    QTest::newRow("dynamicMeta.3") << "dynamicMeta.3.qml" << "dynamicMeta.3.errors.txt" << false;
 +    QTest::newRow("dynamicMeta.4") << "dynamicMeta.4.qml" << "dynamicMeta.4.errors.txt" << false;
 +    QTest::newRow("dynamicMeta.5") << "dynamicMeta.5.qml" << "dynamicMeta.5.errors.txt" << false;
 +
 +    QTest::newRow("invalidAlias.1") << "invalidAlias.1.qml" << "invalidAlias.1.errors.txt" << false;
 +    QTest::newRow("invalidAlias.2") << "invalidAlias.2.qml" << "invalidAlias.2.errors.txt" << false;
 +    QTest::newRow("invalidAlias.3") << "invalidAlias.3.qml" << "invalidAlias.3.errors.txt" << false;
 +    QTest::newRow("invalidAlias.4") << "invalidAlias.4.qml" << "invalidAlias.4.errors.txt" << false;
 +    QTest::newRow("invalidAlias.5") << "invalidAlias.5.qml" << "invalidAlias.5.errors.txt" << false;
 +    QTest::newRow("invalidAlias.6") << "invalidAlias.6.qml" << "invalidAlias.6.errors.txt" << false;
 +    QTest::newRow("invalidAlias.7") << "invalidAlias.7.qml" << "invalidAlias.7.errors.txt" << false;
 +    QTest::newRow("invalidAlias.8") << "invalidAlias.8.qml" << "invalidAlias.8.errors.txt" << false;
 +    QTest::newRow("invalidAlias.9") << "invalidAlias.9.qml" << "invalidAlias.9.errors.txt" << false;
 +    QTest::newRow("invalidAlias.10") << "invalidAlias.10.qml" << "invalidAlias.10.errors.txt" << false;
 +
 +    QTest::newRow("invalidAttachedProperty.1") << "invalidAttachedProperty.1.qml" << "invalidAttachedProperty.1.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.2") << "invalidAttachedProperty.2.qml" << "invalidAttachedProperty.2.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.3") << "invalidAttachedProperty.3.qml" << "invalidAttachedProperty.3.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.4") << "invalidAttachedProperty.4.qml" << "invalidAttachedProperty.4.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.5") << "invalidAttachedProperty.5.qml" << "invalidAttachedProperty.5.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.6") << "invalidAttachedProperty.6.qml" << "invalidAttachedProperty.6.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.7") << "invalidAttachedProperty.7.qml" << "invalidAttachedProperty.7.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.8") << "invalidAttachedProperty.8.qml" << "invalidAttachedProperty.8.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.9") << "invalidAttachedProperty.9.qml" << "invalidAttachedProperty.9.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.10") << "invalidAttachedProperty.10.qml" << "invalidAttachedProperty.10.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.11") << "invalidAttachedProperty.11.qml" << "invalidAttachedProperty.11.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.12") << "invalidAttachedProperty.12.qml" << "invalidAttachedProperty.12.errors.txt" << false;
 +    QTest::newRow("invalidAttachedProperty.13") << "invalidAttachedProperty.13.qml" << "invalidAttachedProperty.13.errors.txt" << false;
 +
 +    QTest::newRow("assignValueToSignal") << "assignValueToSignal.qml" << "assignValueToSignal.errors.txt" << false;
 +    QTest::newRow("emptySignal") << "emptySignal.qml" << "emptySignal.errors.txt" << false;
 +
 +    QTest::newRow("nestedErrors") << "nestedErrors.qml" << "nestedErrors.errors.txt" << false;
 +    QTest::newRow("defaultGrouped") << "defaultGrouped.qml" << "defaultGrouped.errors.txt" << false;
 +    QTest::newRow("doubleSignal") << "doubleSignal.qml" << "doubleSignal.errors.txt" << false;
 +    QTest::newRow("missingValueTypeProperty") << "missingValueTypeProperty.qml" << "missingValueTypeProperty.errors.txt" << false;
 +    QTest::newRow("objectValueTypeProperty") << "objectValueTypeProperty.qml" << "objectValueTypeProperty.errors.txt" << false;
 +    QTest::newRow("enumTypes") << "enumTypes.qml" << "enumTypes.errors.txt" << false;
 +    QTest::newRow("noCreation") << "noCreation.qml" << "noCreation.errors.txt" << false;
 +    QTest::newRow("destroyedSignal") << "destroyedSignal.qml" << "destroyedSignal.errors.txt" << false;
 +    QTest::newRow("assignToNamespace") << "assignToNamespace.qml" << "assignToNamespace.errors.txt" << false;
 +    QTest::newRow("invalidOn") << "invalidOn.qml" << "invalidOn.errors.txt" << false;
 +    QTest::newRow("invalidProperty") << "invalidProperty.qml" << "invalidProperty.errors.txt" << false;
 +    QTest::newRow("nonScriptableProperty") << "nonScriptableProperty.qml" << "nonScriptableProperty.errors.txt" << false;
 +    QTest::newRow("notAvailable") << "notAvailable.qml" << "notAvailable.errors.txt" << false;
 +    QTest::newRow("singularProperty") << "singularProperty.qml" << "singularProperty.errors.txt" << false;
 +    QTest::newRow("singularProperty.2") << "singularProperty.2.qml" << "singularProperty.2.errors.txt" << false;
 +    QTest::newRow("incorrectCase") << "incorrectCase.qml" 
 +#if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
 +        << "incorrectCase.errors.insensitive.txt" 
 +#else
 +        << "incorrectCase.errors.sensitive.txt" 
 +#endif
 +        << false;
 +
 +    QTest::newRow("metaobjectRevision.1") << "metaobjectRevision.1.qml" << "metaobjectRevision.1.errors.txt" << false;
 +    QTest::newRow("metaobjectRevision.2") << "metaobjectRevision.2.qml" << "metaobjectRevision.2.errors.txt" << false;
 +    QTest::newRow("metaobjectRevision.3") << "metaobjectRevision.3.qml" << "metaobjectRevision.3.errors.txt" << false;
 +
 +    QTest::newRow("invalidRoot.1") << "invalidRoot.1.qml" << "invalidRoot.1.errors.txt" << false;
 +    QTest::newRow("invalidRoot.2") << "invalidRoot.2.qml" << "invalidRoot.2.errors.txt" << false;
 +    QTest::newRow("invalidRoot.3") << "invalidRoot.3.qml" << "invalidRoot.3.errors.txt" << false;
 +    QTest::newRow("invalidRoot.4") << "invalidRoot.4.qml" << "invalidRoot.4.errors.txt" << false;
 +
 +    QTest::newRow("invalidTypeName.1") << "invalidTypeName.1.qml" << "invalidTypeName.1.errors.txt" << false;
 +    QTest::newRow("invalidTypeName.2") << "invalidTypeName.2.qml" << "invalidTypeName.2.errors.txt" << false;
 +    QTest::newRow("invalidTypeName.3") << "invalidTypeName.3.qml" << "invalidTypeName.3.errors.txt" << false;
 +    QTest::newRow("invalidTypeName.4") << "invalidTypeName.4.qml" << "invalidTypeName.4.errors.txt" << false;
 +
 +    QTest::newRow("Major version isolation") << "majorVersionIsolation.qml" << "majorVersionIsolation.errors.txt" << false;
 +}
 +
 +
 +void tst_qqmllanguage::errors()
 +{
 +    QFETCH(QString, file);
 +    QFETCH(QString, errorFile);
 +    QFETCH(bool, create);
 +
 +    QQmlComponent component(&engine, TEST_FILE(file));
 +
 +    if(create) {
 +        QObject *object = component.create();
 +        QVERIFY(object == 0);
 +    }
 +
 +    VERIFY_ERRORS(errorFile.toLatin1().constData());
 +}
 +
 +void tst_qqmllanguage::simpleObject()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("simpleObject.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +}
 +
 +void tst_qqmllanguage::simpleContainer()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("simpleContainer.qml"));
 +    VERIFY_ERRORS(0);
 +    MyContainer *container= qobject_cast<MyContainer*>(component.create());
 +    QVERIFY(container != 0);
 +    QCOMPARE(container->getChildren()->count(),2);
 +}
 +
 +void tst_qqmllanguage::interfaceProperty()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("interfaceProperty.qml"));
 +    VERIFY_ERRORS(0);
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +    QVERIFY(object->interface());
 +    QVERIFY(object->interface()->id == 913);
 +}
 +
 +void tst_qqmllanguage::interfaceQList()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("interfaceQList.qml"));
 +    VERIFY_ERRORS(0);
 +    MyContainer *container= qobject_cast<MyContainer*>(component.create());
 +    QVERIFY(container != 0);
 +    QVERIFY(container->getQListInterfaces()->count() == 2);
 +    for(int ii = 0; ii < 2; ++ii)
 +        QVERIFY(container->getQListInterfaces()->at(ii)->id == 913);
 +}
 +
 +void tst_qqmllanguage::assignObjectToSignal()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("assignObjectToSignal.qml"));
 +    VERIFY_ERRORS(0);
 +    MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
 +    emit object->basicSignal();
 +}
 +
 +void tst_qqmllanguage::assignObjectToVariant()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("assignObjectToVariant.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QVariant v = object->property("a");
 +    QVERIFY(v.userType() == qMetaTypeId<QObject *>());
 +}
 +
 +void tst_qqmllanguage::assignLiteralSignalProperty()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("assignLiteralSignalProperty.qml"));
 +    VERIFY_ERRORS(0);
 +    MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->onLiteralSignal(), 10);
 +}
 +
 +// Test is an external component can be loaded and assigned (to a qlist)
 +void tst_qqmllanguage::assignQmlComponent()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("assignQmlComponent.qml"));
 +    VERIFY_ERRORS(0);
 +    MyContainer *object = qobject_cast<MyContainer *>(component.create());
 +    QVERIFY(object != 0);
 +    QVERIFY(object->getChildren()->count() == 1);
 +    QObject *child = object->getChildren()->at(0);
 +    QCOMPARE(child->property("x"), QVariant(10));
 +    QCOMPARE(child->property("y"), QVariant(11));
 +}
 +
 +// Test literal assignment to all the basic types 
 +void tst_qqmllanguage::assignBasicTypes()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
 +    VERIFY_ERRORS(0);
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
 +    QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
 +    QCOMPARE(object->stringProperty(), QString("Hello World!"));
 +    QCOMPARE(object->uintProperty(), uint(10));
 +    QCOMPARE(object->intProperty(), -19);
 +    QCOMPARE((float)object->realProperty(), float(23.2));
 +    QCOMPARE((float)object->doubleProperty(), float(-19.7));
 +    QCOMPARE((float)object->floatProperty(), float(8.5));
 +    QCOMPARE(object->colorProperty(), QColor("red"));
 +    QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
 +    QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
 +    QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
 +    QCOMPARE(object->pointProperty(), QPoint(99,13));
 +    QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
 +    QCOMPARE(object->sizeProperty(), QSize(99, 13));
 +    QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
 +    QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
 +    QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
 +    QCOMPARE(object->boolProperty(), true);
 +    QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
 +    QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
 +    QCOMPARE(object->vector4Property(), QVector4D(10, 1, 2.2, 2.3));
 +    QUrl encoded;
 +    encoded.setEncodedUrl("main.qml?with%3cencoded%3edata", QUrl::TolerantMode);
 +    QCOMPARE(object->urlProperty(), component.url().resolved(encoded));
 +    QVERIFY(object->objectProperty() != 0);
 +    MyTypeObject *child = qobject_cast<MyTypeObject *>(object->objectProperty());
 +    QVERIFY(child != 0);
 +    QCOMPARE(child->intProperty(), 8);
 +}
 +
 +// Test edge case type assignments
 +void tst_qqmllanguage::assignTypeExtremes()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("assignTypeExtremes.qml"));
 +    VERIFY_ERRORS(0);
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->uintProperty(), 0xEE6B2800);
 +    QCOMPARE(object->intProperty(), -0x77359400);
 +}
 +
 +// Test that a composite type can assign to a property of its base type
 +void tst_qqmllanguage::assignCompositeToType()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("assignCompositeToType.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +}
 +
 +// Test that literals are stored correctly in variant properties
 +void tst_qqmllanguage::assignLiteralToVariant()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("assignLiteralToVariant.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test1").userType(), (int)QVariant::Int);
 +    QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
 +    QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
 +    QCOMPARE(object->property("test4").userType(), (int)QVariant::Color);
 +    QCOMPARE(object->property("test5").userType(), (int)QVariant::RectF);
 +    QCOMPARE(object->property("test6").userType(), (int)QVariant::PointF);
 +    QCOMPARE(object->property("test7").userType(), (int)QVariant::SizeF);
 +    QCOMPARE(object->property("test8").userType(), (int)QVariant::Vector3D);
 +    QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
 +    QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
 +    QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
 +    QCOMPARE(object->property("test12").userType(), (int)QVariant::Vector4D);
 +
 +    QVERIFY(object->property("test1") == QVariant(1));
 +    QVERIFY(object->property("test2") == QVariant((double)1.7));
 +    QVERIFY(object->property("test3") == QVariant(QString(QLatin1String("Hello world!"))));
 +    QVERIFY(object->property("test4") == QVariant(QColor::fromRgb(0xFF008800)));
 +    QVERIFY(object->property("test5") == QVariant(QRectF(10, 10, 10, 10)));
 +    QVERIFY(object->property("test6") == QVariant(QPointF(10, 10)));
 +    QVERIFY(object->property("test7") == QVariant(QSizeF(10, 10)));
 +    QVERIFY(object->property("test8") == QVariant(QVector3D(100, 100, 100)));
 +    QVERIFY(object->property("test9") == QVariant(QString(QLatin1String("#FF008800"))));
 +    QVERIFY(object->property("test10") == QVariant(bool(true)));
 +    QVERIFY(object->property("test11") == QVariant(bool(false)));
 +    QVERIFY(object->property("test12") == QVariant(QVector4D(100, 100, 100, 100)));
 +
 +    delete object;
 +}
 +
 +// Test that literals are stored correctly in "var" properties
 +// Note that behaviour differs from "variant" properties in that
 +// no conversion from "special strings" to QVariants is performed.
 +void tst_qqmllanguage::assignLiteralToVar()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("assignLiteralToVar.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test1").userType(), (int)QMetaType::Int);
 +    QCOMPARE(object->property("test2").userType(), (int)QMetaType::Double);
 +    QCOMPARE(object->property("test3").userType(), (int)QVariant::String);
 +    QCOMPARE(object->property("test4").userType(), (int)QVariant::String);
 +    QCOMPARE(object->property("test5").userType(), (int)QVariant::String);
 +    QCOMPARE(object->property("test6").userType(), (int)QVariant::String);
 +    QCOMPARE(object->property("test7").userType(), (int)QVariant::String);
 +    QCOMPARE(object->property("test8").userType(), (int)QVariant::String);
 +    QCOMPARE(object->property("test9").userType(), (int)QVariant::String);
 +    QCOMPARE(object->property("test10").userType(), (int)QVariant::Bool);
 +    QCOMPARE(object->property("test11").userType(), (int)QVariant::Bool);
 +    QCOMPARE(object->property("test12").userType(), (int)QVariant::Color);
 +    QCOMPARE(object->property("test13").userType(), (int)QVariant::RectF);
 +    QCOMPARE(object->property("test14").userType(), (int)QVariant::PointF);
 +    QCOMPARE(object->property("test15").userType(), (int)QVariant::SizeF);
 +    QCOMPARE(object->property("test16").userType(), (int)QVariant::Vector3D);
 +    QCOMPARE(object->property("variantTest1Bound").userType(), (int)QMetaType::Int);
 +    QCOMPARE(object->property("test1Bound").userType(), (int)QMetaType::Int);
 +
 +    QCOMPARE(object->property("test1"), QVariant(5));
 +    QCOMPARE(object->property("test2"), QVariant((double)1.7));
 +    QCOMPARE(object->property("test3"), QVariant(QString(QLatin1String("Hello world!"))));
 +    QCOMPARE(object->property("test4"), QVariant(QString(QLatin1String("#FF008800"))));
 +    QCOMPARE(object->property("test5"), QVariant(QString(QLatin1String("10,10,10x10"))));
 +    QCOMPARE(object->property("test6"), QVariant(QString(QLatin1String("10,10"))));
 +    QCOMPARE(object->property("test7"), QVariant(QString(QLatin1String("10x10"))));
 +    QCOMPARE(object->property("test8"), QVariant(QString(QLatin1String("100,100,100"))));
 +    QCOMPARE(object->property("test9"), QVariant(QString(QLatin1String("#FF008800"))));
 +    QCOMPARE(object->property("test10"), QVariant(bool(true)));
 +    QCOMPARE(object->property("test11"), QVariant(bool(false)));
 +    QCOMPARE(object->property("test12"), QVariant(QColor::fromRgbF(0.2, 0.3, 0.4, 0.5)));
 +    QCOMPARE(object->property("test13"), QVariant(QRectF(10, 10, 10, 10)));
 +    QCOMPARE(object->property("test14"), QVariant(QPointF(10, 10)));
 +    QCOMPARE(object->property("test15"), QVariant(QSizeF(10, 10)));
 +    QCOMPARE(object->property("test16"), QVariant(QVector3D(100, 100, 100)));
 +    QCOMPARE(object->property("variantTest1Bound"), QVariant(9));
 +    QCOMPARE(object->property("test1Bound"), QVariant(11));
 +
 +    delete object;
 +}
 +
 +// Tests that custom parser types can be instantiated
 +void tst_qqmllanguage::customParserTypes()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("customParserTypes.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(object->property("count") == QVariant(2));
 +}
 +
 +// Tests that the root item can be a custom component
 +void tst_qqmllanguage::rootAsQmlComponent()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("rootAsQmlComponent.qml"));
 +    VERIFY_ERRORS(0);
 +    MyContainer *object = qobject_cast<MyContainer *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->property("x"), QVariant(11));
 +    QCOMPARE(object->getChildren()->count(), 2);
 +}
 +
 +// Tests that components can be specified inline
 +void tst_qqmllanguage::inlineQmlComponents()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("inlineQmlComponents.qml"));
 +    VERIFY_ERRORS(0);
 +    MyContainer *object = qobject_cast<MyContainer *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->getChildren()->count(), 1);
 +    QQmlComponent *comp = qobject_cast<QQmlComponent *>(object->getChildren()->at(0));
 +    QVERIFY(comp != 0);
 +    MyQmlObject *compObject = qobject_cast<MyQmlObject *>(comp->create());
 +    QVERIFY(compObject != 0);
 +    QCOMPARE(compObject->value(), 11);
 +}
 +
 +// Tests that types that have an id property have it set
 +void tst_qqmllanguage::idProperty()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("idProperty.qml"));
 +    VERIFY_ERRORS(0);
 +    MyContainer *object = qobject_cast<MyContainer *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->getChildren()->count(), 1);
 +    MyTypeObject *child = 
 +        qobject_cast<MyTypeObject *>(object->getChildren()->at(0));
 +    QVERIFY(child != 0);
 +    QCOMPARE(child->id(), QString("myObjectId"));
 +    QCOMPARE(object->property("object"), QVariant::fromValue((QObject *)child));
 +}
 +
 +// Tests automatic connection to notify signals if "onBlahChanged" syntax is used
 +// even if the notify signal for "blah" is not called "blahChanged"
 +void tst_qqmllanguage::autoNotifyConnection()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("autoNotifyConnection.qml"));
 +    VERIFY_ERRORS(0);
 +    MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QMetaProperty prop = object->metaObject()->property(object->metaObject()->indexOfProperty("receivedNotify"));
 +    QVERIFY(prop.isValid());
 +
 +    QCOMPARE(prop.read(object), QVariant::fromValue(false));
 +    object->setPropertyWithNotify(1);
 +    QCOMPARE(prop.read(object), QVariant::fromValue(true));
 +}
 +
 +// Tests that signals can be assigned to
 +void tst_qqmllanguage::assignSignal()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("assignSignal.qml"));
 +    VERIFY_ERRORS(0);
 +    MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlot");
 +    emit object->basicSignal();
 +    QTest::ignoreMessage(QtWarningMsg, "MyQmlObject::basicSlotWithArgs(9)");
 +    emit object->basicParameterizedSignal(9);
 +}
 +
 +// Tests the creation and assignment of dynamic properties
 +void tst_qqmllanguage::dynamicProperties()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("dynamicProperties.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->property("intProperty"), QVariant(10));
 +    QCOMPARE(object->property("boolProperty"), QVariant(false));
 +    QCOMPARE(object->property("doubleProperty"), QVariant(-10.1));
 +    QCOMPARE(object->property("realProperty"), QVariant((qreal)-19.9));
 +    QCOMPARE(object->property("stringProperty"), QVariant("Hello World!"));
 +    QCOMPARE(object->property("urlProperty"), QVariant(TEST_FILE("main.qml")));
 +    QCOMPARE(object->property("colorProperty"), QVariant(QColor("red")));
 +    QCOMPARE(object->property("dateProperty"), QVariant(QDate(1945, 9, 2)));
 +    QCOMPARE(object->property("varProperty"), QVariant("Hello World!"));
 +}
 +
 +// Test that nested types can use dynamic properties
 +void tst_qqmllanguage::dynamicPropertiesNested()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("dynamicPropertiesNested.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("super_a").toInt(), 11); // Overridden
 +    QCOMPARE(object->property("super_c").toInt(), 14); // Inherited
 +    QCOMPARE(object->property("a").toInt(), 13); // New
 +    QCOMPARE(object->property("b").toInt(), 12); // New
 +
 +    delete object;
 +}
 +
 +// Tests the creation and assignment to dynamic list properties
 +void tst_qqmllanguage::listProperties()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("listProperties.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toInt(), 2);
 +}
 +
 +// Tests the creation and assignment of dynamic object properties
 +// ### Not complete
 +void tst_qqmllanguage::dynamicObjectProperties()
 +{
 +    {
 +    QQmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QVERIFY(object->property("objectProperty") == qVariantFromValue((QObject*)0));
 +    QVERIFY(object->property("objectProperty2") != qVariantFromValue((QObject*)0));
 +    }
 +    {
 +    QQmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.2.qml"));
 +    QEXPECT_FAIL("", "QTBUG-10822", Abort);
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QVERIFY(object->property("objectProperty") != qVariantFromValue((QObject*)0));
 +    }
 +}
 +
 +// Tests the declaration of dynamic signals and slots
 +void tst_qqmllanguage::dynamicSignalsAndSlots()
 +{
 +    QTest::ignoreMessage(QtDebugMsg, "1921");
 +
 +    QQmlComponent component(&engine, TEST_FILE("dynamicSignalsAndSlots.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QVERIFY(object->metaObject()->indexOfMethod("signal1()") != -1);
 +    QVERIFY(object->metaObject()->indexOfMethod("signal2()") != -1);
 +    QVERIFY(object->metaObject()->indexOfMethod("slot1()") != -1);
 +    QVERIFY(object->metaObject()->indexOfMethod("slot2()") != -1);
 +
 +    QCOMPARE(object->property("test").toInt(), 0);
 +    QMetaObject::invokeMethod(object, "slot3", Qt::DirectConnection, Q_ARG(QVariant, QVariant(10)));
 +    QCOMPARE(object->property("test").toInt(), 10);
 +}
 +
 +void tst_qqmllanguage::simpleBindings()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("simpleBindings.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->property("value1"), QVariant(10));
 +    QCOMPARE(object->property("value2"), QVariant(10));
 +    QCOMPARE(object->property("value3"), QVariant(21));
 +    QCOMPARE(object->property("value4"), QVariant(10));
 +    QCOMPARE(object->property("objectProperty"), QVariant::fromValue(object));
 +}
 +
 +void tst_qqmllanguage::autoComponentCreation()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("autoComponentCreation.qml"));
 +    VERIFY_ERRORS(0);
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QVERIFY(object->componentProperty() != 0);
 +    MyTypeObject *child = qobject_cast<MyTypeObject *>(object->componentProperty()->create());
 +    QVERIFY(child != 0);
 +    QCOMPARE(child->realProperty(), qreal(9));
 +}
 +
 +void tst_qqmllanguage::propertyValueSource()
 +{
 +    {
 +    QQmlComponent component(&engine, TEST_FILE("propertyValueSource.qml"));
 +    VERIFY_ERRORS(0);
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QList<QObject *> valueSources;
 +    QObjectList allChildren = object->findChildren<QObject*>();
 +    foreach (QObject *child, allChildren) {
 +        if (qobject_cast<QQmlPropertyValueSource *>(child)) 
 +            valueSources.append(child);
 +    }
 +
 +    QCOMPARE(valueSources.count(), 1);
 +    MyPropertyValueSource *valueSource = 
 +        qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
 +    QVERIFY(valueSource != 0);
 +    QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
 +    QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, TEST_FILE("propertyValueSource.2.qml"));
 +    VERIFY_ERRORS(0);
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QList<QObject *> valueSources;
 +    QObjectList allChildren = object->findChildren<QObject*>();
 +    foreach (QObject *child, allChildren) {
 +        if (qobject_cast<QQmlPropertyValueSource *>(child)) 
 +            valueSources.append(child);
 +    }
 +
 +    QCOMPARE(valueSources.count(), 1);
 +    MyPropertyValueSource *valueSource = 
 +        qobject_cast<MyPropertyValueSource *>(valueSources.at(0));
 +    QVERIFY(valueSource != 0);
 +    QCOMPARE(valueSource->prop.object(), qobject_cast<QObject*>(object));
 +    QCOMPARE(valueSource->prop.name(), QString(QLatin1String("intProperty")));
 +    }
 +}
 +
 +void tst_qqmllanguage::attachedProperties()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("attachedProperties.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QObject *attached = qmlAttachedPropertiesObject<MyQmlObject>(object);
 +    QVERIFY(attached != 0);
 +    QCOMPARE(attached->property("value"), QVariant(10));
 +    QCOMPARE(attached->property("value2"), QVariant(13));
 +}
 +
 +// Tests non-static object properties
 +void tst_qqmllanguage::dynamicObjects()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("dynamicObject.1.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +}
 +
 +// Tests the registration of custom variant string converters
 +void tst_qqmllanguage::customVariantTypes()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("customVariantTypes.qml"));
 +    VERIFY_ERRORS(0);
 +    MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->customType().a, 10);
 +}
 +
 +void tst_qqmllanguage::valueTypes()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("valueTypes.qml"));
 +    VERIFY_ERRORS(0);
 +
 +    QString message = component.url().toString() + ":2:1: QML MyTypeObject: Binding loop detected for property \"rectProperty.width\"";
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
 +
 +    MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
 +    QVERIFY(object != 0);
 +
 +
 +    QCOMPARE(object->rectProperty(), QRect(10, 11, 12, 13));
 +    QCOMPARE(object->rectProperty2(), QRect(10, 11, 12, 13));
 +    QCOMPARE(object->intProperty(), 10);
 +    object->doAction();
 +    QCOMPARE(object->rectProperty(), QRect(12, 11, 14, 13));
 +    QCOMPARE(object->rectProperty2(), QRect(12, 11, 14, 13));
 +    QCOMPARE(object->intProperty(), 12);
 +
 +    // ###
 +#if 0
 +    QQmlProperty p(object, "rectProperty.x");
 +    QCOMPARE(p.read(), QVariant(12));
 +    p.write(13);
 +    QCOMPARE(p.read(), QVariant(13));
 +
 +    quint32 r = QQmlPropertyPrivate::saveValueType(p.coreIndex(), p.valueTypeCoreIndex());
 +    QQmlProperty p2;
 +    QQmlPropertyPrivate::restore(p2, r, object);
 +    QCOMPARE(p2.read(), QVariant(13));
 +#endif
 +}
 +
 +void tst_qqmllanguage::cppnamespace()
 +{
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("cppnamespace.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("cppnamespace.2.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmllanguage::aliasProperties()
 +{
 +    // Simple "int" alias
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.1.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        // Read through alias
 +        QCOMPARE(object->property("valueAlias").toInt(), 10);
 +        object->setProperty("value", QVariant(13));
 +        QCOMPARE(object->property("valueAlias").toInt(), 13);
 +
 +        // Write through alias
 +        object->setProperty("valueAlias", QVariant(19));
 +        QCOMPARE(object->property("valueAlias").toInt(), 19);
 +        QCOMPARE(object->property("value").toInt(), 19);
 +
 +        delete object;
 +    }
 +
 +    // Complex object alias
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.2.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        // Read through alias
 +        MyQmlObject *v = 
 +            qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
 +        QVERIFY(v != 0);
 +        QCOMPARE(v->value(), 10);
 +
 +        // Write through alias
 +        MyQmlObject *v2 = new MyQmlObject();
 +        v2->setParent(object);
 +        object->setProperty("aliasObject", qVariantFromValue(v2));
 +        MyQmlObject *v3 = 
 +            qvariant_cast<MyQmlObject *>(object->property("aliasObject"));
 +        QVERIFY(v3 != 0);
 +        QCOMPARE(v3, v2);
 +
 +        delete object;
 +    }
 +
 +    // Nested aliases
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.3.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("value").toInt(), 1892);
 +        QCOMPARE(object->property("value2").toInt(), 1892);
 +
 +        object->setProperty("value", QVariant(1313));
 +        QCOMPARE(object->property("value").toInt(), 1313);
 +        QCOMPARE(object->property("value2").toInt(), 1313);
 +
 +        object->setProperty("value2", QVariant(8080));
 +        QCOMPARE(object->property("value").toInt(), 8080);
 +        QCOMPARE(object->property("value2").toInt(), 8080);
 +
 +        delete object;
 +    }
 +
 +    // Enum aliases
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.4.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("enumAlias").toInt(), 1);
 +
 +        delete object;
 +    }
 +
 +    // Id aliases
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.5.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QVariant v = object->property("otherAlias");
 +        QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
 +        MyQmlObject *o = qvariant_cast<MyQmlObject*>(v);
 +        QCOMPARE(o->value(), 10);
 +
 +        delete o;
 +
 +        v = object->property("otherAlias");
 +        QCOMPARE(v.userType(), qMetaTypeId<MyQmlObject*>());
 +        o = qvariant_cast<MyQmlObject*>(v);
 +        QVERIFY(o == 0);
 +
 +        delete object;
 +    }
 +
 +    // Nested aliases - this used to cause a crash
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.6.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("a").toInt(), 1923);
 +    }
 +
 +    // Ptr Alias Cleanup - check that aliases to ptr types return 0 
 +    // if the object aliased to is removed
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.7.qml"));
 +        VERIFY_ERRORS(0);
 +
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QObject *object1 = qvariant_cast<QObject *>(object->property("object"));
 +        QVERIFY(object1 != 0);
 +        QObject *object2 = qvariant_cast<QObject *>(object1->property("object"));
 +        QVERIFY(object2 != 0);
 +
 +        QObject *alias = qvariant_cast<QObject *>(object->property("aliasedObject"));
 +        QVERIFY(alias == object2);
 +
 +        delete object1;
 +
 +        QObject *alias2 = object; // "Random" start value
 +        int status = -1;
 +        void *a[] = { &alias2, 0, &status };
 +        QMetaObject::metacall(object, QMetaObject::ReadProperty,
 +                              object->metaObject()->indexOfProperty("aliasedObject"), a);
 +        QVERIFY(alias2 == 0);
 +    }
 +
 +    // Simple composite type
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.8.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("value").toInt(), 10);
 +
 +        delete object;
 +    }
 +
 +    // Complex composite type
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.9.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("value").toInt(), 10);
 +
 +        delete object;
 +    }
 +
 +    // Valuetype alias
 +    // Simple "int" alias
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.10.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        // Read through alias
 +        QCOMPARE(object->property("valueAlias").toRect(), QRect(10, 11, 9, 8));
 +        object->setProperty("rectProperty", QVariant(QRect(33, 12, 99, 100)));
 +        QCOMPARE(object->property("valueAlias").toRect(), QRect(33, 12, 99, 100));
 +
 +        // Write through alias
 +        object->setProperty("valueAlias", QVariant(QRect(3, 3, 4, 9)));
 +        QCOMPARE(object->property("valueAlias").toRect(), QRect(3, 3, 4, 9));
 +        QCOMPARE(object->property("rectProperty").toRect(), QRect(3, 3, 4, 9));
 +
 +        delete object;
 +    }
 +
 +    // Valuetype sub-alias
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("alias.11.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        // Read through alias
 +        QCOMPARE(object->property("aliasProperty").toInt(), 19);
 +        object->setProperty("rectProperty", QVariant(QRect(33, 8, 102, 111)));
 +        QCOMPARE(object->property("aliasProperty").toInt(), 33);
 +
 +        // Write through alias
 +        object->setProperty("aliasProperty", QVariant(4));
 +        QCOMPARE(object->property("aliasProperty").toInt(), 4);
 +        QCOMPARE(object->property("rectProperty").toRect(), QRect(4, 8, 102, 111));
 +
 +        delete object;
 +    }
 +}
 +
 +// QTBUG-13374 Test that alias properties and signals can coexist
 +void tst_qqmllanguage::aliasPropertiesAndSignals()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("aliasPropertiesAndSignals.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *o = component.create();
 +    QVERIFY(o);
 +    QCOMPARE(o->property("test").toBool(), true);
 +    delete o;
 +}
 +
 +// Test that the root element in a composite type can be a Component
 +void tst_qqmllanguage::componentCompositeType()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("componentCompositeType.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +}
 +
 +class TestType : public QObject {
 +    Q_OBJECT
 +public:
 +    TestType(QObject *p=0) : QObject(p) {}
 +};
 +
 +class TestType2 : public QObject {
 +    Q_OBJECT
 +public:
 +    TestType2(QObject *p=0) : QObject(p) {}
 +};
 +
 +void tst_qqmllanguage::i18n_data()
 +{
 +    QTest::addColumn<QString>("file");
 +    QTest::addColumn<QString>("stringProperty");
 +    QTest::newRow("i18nStrings") << "i18nStrings.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245 (5 accented 'a' letters)");
 +    QTest::newRow("i18nDeclaredPropertyNames") << "i18nDeclaredPropertyNames.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 10");
 +    QTest::newRow("i18nDeclaredPropertyUse") << "i18nDeclaredPropertyUse.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 15");
 +    QTest::newRow("i18nScript") << "i18nScript.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 20");
 +    QTest::newRow("i18nType") << "i18nType.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 30");
 +    QTest::newRow("i18nNameSpace") << "i18nNameSpace.qml" << QString::fromUtf8("Test \303\241\303\242\303\243\303\244\303\245: 40");
 +}
 +
 +void tst_qqmllanguage::i18n()
 +{
 +    QFETCH(QString, file);
 +    QFETCH(QString, stringProperty);
 +    QQmlComponent component(&engine, TEST_FILE(file));
 +    VERIFY_ERRORS(0);
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QCOMPARE(object->stringProperty(), stringProperty);
 +
 +    delete object;
 +}
 +
 +// Check that the Component::onCompleted attached property works
 +void tst_qqmllanguage::onCompleted()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("onCompleted.qml"));
 +    VERIFY_ERRORS(0);
 +    QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
 +    QTest::ignoreMessage(QtDebugMsg, "Completed 6 10");
 +    QTest::ignoreMessage(QtDebugMsg, "Completed 10 11");
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +}
 +
 +// Check that the Component::onDestruction attached property works
 +void tst_qqmllanguage::onDestruction()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("onDestruction.qml"));
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +    QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10");
 +    QTest::ignoreMessage(QtDebugMsg, "Destruction 6 10");
 +    QTest::ignoreMessage(QtDebugMsg, "Destruction 10 11");
 +    delete object;
 +}
 +
 +// Check that assignments to QQmlScriptString properties work
 +void tst_qqmllanguage::scriptString()
 +{
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("scriptString.qml"));
 +        VERIFY_ERRORS(0);
 +
 +        MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->scriptProperty().script(), QString("foo + bar"));
 +        QCOMPARE(object->scriptProperty().scopeObject(), qobject_cast<QObject*>(object));
 +        QCOMPARE(object->scriptProperty().context(), qmlContext(object));
 +
 +        QVERIFY(object->grouped() != 0);
 +        QCOMPARE(object->grouped()->script().script(), QString("console.log(1921)"));
 +        QCOMPARE(object->grouped()->script().scopeObject(), qobject_cast<QObject*>(object));
 +        QCOMPARE(object->grouped()->script().context(), qmlContext(object));
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("scriptString2.qml"));
 +        VERIFY_ERRORS(0);
 +
 +        MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->scriptProperty().script(), QString("\"hello\\n\\\"world\\\"\""));
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("scriptString3.qml"));
 +        VERIFY_ERRORS(0);
 +
 +        MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->scriptProperty().script(), QString("12.345"));
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("scriptString4.qml"));
 +        VERIFY_ERRORS(0);
 +
 +        MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create());
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->scriptProperty().script(), QString("true"));
 +    }
 +}
 +
 +// Check that default property assignments are correctly spliced into explicit 
 +// property assignments
 +void tst_qqmllanguage::defaultPropertyListOrder()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("defaultPropertyListOrder.qml"));
 +    VERIFY_ERRORS(0);
 +
 +    MyContainer *container = qobject_cast<MyContainer *>(component.create());
 +    QVERIFY(container  != 0);
 +
 +    QCOMPARE(container->getChildren()->count(), 6);
 +    QCOMPARE(container->getChildren()->at(0)->property("index"), QVariant(0));
 +    QCOMPARE(container->getChildren()->at(1)->property("index"), QVariant(1));
 +    QCOMPARE(container->getChildren()->at(2)->property("index"), QVariant(2));
 +    QCOMPARE(container->getChildren()->at(3)->property("index"), QVariant(3));
 +    QCOMPARE(container->getChildren()->at(4)->property("index"), QVariant(4));
 +    QCOMPARE(container->getChildren()->at(5)->property("index"), QVariant(5));
 +}
 +
 +void tst_qqmllanguage::declaredPropertyValues()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("declaredPropertyValues.qml"));
 +    VERIFY_ERRORS(0);
 +}
 +
 +void tst_qqmllanguage::dontDoubleCallClassBegin()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("dontDoubleCallClassBegin.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o);
 +
 +    MyParserStatus *o2 = qobject_cast<MyParserStatus *>(qvariant_cast<QObject *>(o->property("object")));
 +    QVERIFY(o2);
 +    QCOMPARE(o2->classBeginCount(), 1);
 +    QCOMPARE(o2->componentCompleteCount(), 1);
 +
 +    delete o;
 +}
 +
 +void tst_qqmllanguage::reservedWords_data()
 +{
 +    QTest::addColumn<QByteArray>("word");
 +
 +    QTest::newRow("abstract") << QByteArray("abstract");
 +    QTest::newRow("as") << QByteArray("as");
 +    QTest::newRow("boolean") << QByteArray("boolean");
 +    QTest::newRow("break") << QByteArray("break");
 +    QTest::newRow("byte") << QByteArray("byte");
 +    QTest::newRow("case") << QByteArray("case");
 +    QTest::newRow("catch") << QByteArray("catch");
 +    QTest::newRow("char") << QByteArray("char");
 +    QTest::newRow("class") << QByteArray("class");
 +    QTest::newRow("continue") << QByteArray("continue");
 +    QTest::newRow("const") << QByteArray("const");
 +    QTest::newRow("debugger") << QByteArray("debugger");
 +    QTest::newRow("default") << QByteArray("default");
 +    QTest::newRow("delete") << QByteArray("delete");
 +    QTest::newRow("do") << QByteArray("do");
 +    QTest::newRow("double") << QByteArray("double");
 +    QTest::newRow("else") << QByteArray("else");
 +    QTest::newRow("enum") << QByteArray("enum");
 +    QTest::newRow("export") << QByteArray("export");
 +    QTest::newRow("extends") << QByteArray("extends");
 +    QTest::newRow("false") << QByteArray("false");
 +    QTest::newRow("final") << QByteArray("final");
 +    QTest::newRow("finally") << QByteArray("finally");
 +    QTest::newRow("float") << QByteArray("float");
 +    QTest::newRow("for") << QByteArray("for");
 +    QTest::newRow("function") << QByteArray("function");
 +    QTest::newRow("goto") << QByteArray("goto");
 +    QTest::newRow("if") << QByteArray("if");
 +    QTest::newRow("implements") << QByteArray("implements");
 +    QTest::newRow("import") << QByteArray("import");
 +    QTest::newRow("in") << QByteArray("in");
 +    QTest::newRow("instanceof") << QByteArray("instanceof");
 +    QTest::newRow("int") << QByteArray("int");
 +    QTest::newRow("interface") << QByteArray("interface");
 +    QTest::newRow("long") << QByteArray("long");
 +    QTest::newRow("native") << QByteArray("native");
 +    QTest::newRow("new") << QByteArray("new");
 +    QTest::newRow("null") << QByteArray("null");
 +    QTest::newRow("package") << QByteArray("package");
 +    QTest::newRow("private") << QByteArray("private");
 +    QTest::newRow("protected") << QByteArray("protected");
 +    QTest::newRow("public") << QByteArray("public");
 +    QTest::newRow("return") << QByteArray("return");
 +    QTest::newRow("short") << QByteArray("short");
 +    QTest::newRow("static") << QByteArray("static");
 +    QTest::newRow("super") << QByteArray("super");
 +    QTest::newRow("switch") << QByteArray("switch");
 +    QTest::newRow("synchronized") << QByteArray("synchronized");
 +    QTest::newRow("this") << QByteArray("this");
 +    QTest::newRow("throw") << QByteArray("throw");
 +    QTest::newRow("throws") << QByteArray("throws");
 +    QTest::newRow("transient") << QByteArray("transient");
 +    QTest::newRow("true") << QByteArray("true");
 +    QTest::newRow("try") << QByteArray("try");
 +    QTest::newRow("typeof") << QByteArray("typeof");
 +    QTest::newRow("var") << QByteArray("var");
 +    QTest::newRow("void") << QByteArray("void");
 +    QTest::newRow("volatile") << QByteArray("volatile");
 +    QTest::newRow("while") << QByteArray("while");
 +    QTest::newRow("with") << QByteArray("with");
 +}
 +
 +void tst_qqmllanguage::reservedWords()
 +{
 +    QFETCH(QByteArray, word);
 +    QQmlComponent component(&engine);
 +    component.setData("import QtQuick 2.0\nQtObject { property string " + word + " }", QUrl());
 +    QCOMPARE(component.errorString(), QLatin1String(":2 Expected token `identifier'\n"));
 +}
 +
 +// Check that first child of qml is of given type. Empty type insists on error.
 +void tst_qqmllanguage::testType(const QString& qml, const QString& type, const QString& expectederror)
 +{
 +    QQmlComponent component(&engine);
 +    component.setData(qml.toUtf8(), TEST_FILE("empty.qml")); // just a file for relative local imports
 +
 +    QTRY_VERIFY(!component.isLoading());
 +
 +    if (type.isEmpty()) {
 +        QVERIFY(component.isError());
 +        QString actualerror;
 +        foreach (const QQmlError e, component.errors()) {
 +            if (!actualerror.isEmpty())
 +                actualerror.append("; ");
 +            actualerror.append(e.description());
 +        }
 +        QCOMPARE(actualerror,expectederror);
 +    } else {
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        QCOMPARE(QString(object->metaObject()->className()), type);
 +        delete object;
 +    }
 +}
 +
 +// QTBUG-17276
 +void tst_qqmllanguage::inlineAssignmentsOverrideBindings()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("inlineAssignmentsOverrideBindings.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test").toInt(), 11);
 +    delete o;
 +}
 +
 +// QTBUG-19354
 +void tst_qqmllanguage::nestedComponentRoots()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("nestedComponentRoots.qml"));
 +}
 +
 +// Import tests (QT-558)
 +void tst_qqmllanguage::importsBuiltin_data()
 +{
 +    // QT-610
 +
 +    QTest::addColumn<QString>("qml");
 +    QTest::addColumn<QString>("type");
 +    QTest::addColumn<QString>("error");
 +
 +    // import built-ins
 +    QTest::newRow("missing import")
 +        << "Test {}"
 +        << ""
 +        << "Test is not a type";
 +    QTest::newRow("not in version 0.0")
 +        << "import com.nokia.Test 0.0\n"
 +           "Test {}"
 +        << ""
 +        << "Test is not a type";
 +    QTest::newRow("version not installed")
 +        << "import com.nokia.Test 99.0\n"
 +           "Test {}"
 +        << ""
 +        << "module \"com.nokia.Test\" version 99.0 is not installed";
 +    QTest::newRow("in version 0.0")
 +        << "import com.nokia.Test 0.0\n"
 +           "TestTP {}"
 +        << "TestType"
 +        << "";
 +    QTest::newRow("qualified in version 0.0")
 +        << "import com.nokia.Test 0.0 as T\n"
 +           "T.TestTP {}"
 +        << "TestType"
 +        << "";
 +    QTest::newRow("in version 1.0")
 +        << "import com.nokia.Test 1.0\n"
 +           "Test {}"
 +        << "TestType"
 +        << "";
 +    QTest::newRow("qualified wrong")
 +        << "import com.nokia.Test 1.0 as T\n" // QT-610
 +           "Test {}"
 +        << ""
 +        << "Test is not a type";
 +    QTest::newRow("qualified right")
 +        << "import com.nokia.Test 1.0 as T\n"
 +           "T.Test {}"
 +        << "TestType"
 +        << "";
 +    QTest::newRow("qualified right but not in version 0.0")
 +        << "import com.nokia.Test 0.0 as T\n"
 +           "T.Test {}"
 +        << ""
 +        << "T.Test is not a type";
 +    QTest::newRow("in version 1.1")
 +        << "import com.nokia.Test 1.1\n"
 +           "Test {}"
 +        << "TestType"
 +        << "";
 +    QTest::newRow("in version 1.3")
 +        << "import com.nokia.Test 1.3\n"
 +           "Test {}"
 +        << "TestType"
 +        << "";
 +    QTest::newRow("in version 1.5")
 +        << "import com.nokia.Test 1.5\n"
 +           "Test {}"
 +        << "TestType"
 +        << "";
 +    QTest::newRow("changed in version 1.8")
 +        << "import com.nokia.Test 1.8\n"
 +           "Test {}"
 +        << "TestType2"
 +        << "";
 +    QTest::newRow("in version 1.12")
 +        << "import com.nokia.Test 1.12\n"
 +           "Test {}"
 +        << "TestType2"
 +        << "";
 +    QTest::newRow("old in version 1.9")
 +        << "import com.nokia.Test 1.9\n"
 +           "OldTest {}"
 +        << "TestType"
 +        << "";
 +    QTest::newRow("old in version 1.11")
 +        << "import com.nokia.Test 1.11\n"
 +           "OldTest {}"
 +        << "TestType"
 +        << "";
 +    QTest::newRow("multiversion 1")
 +        << "import com.nokia.Test 1.11\n"
 +           "import com.nokia.Test 1.12\n"
 +           "Test {}"
 +        << (!qmlCheckTypes()?"TestType2":"")
 +        << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test in version 1.12 and 1.11");
 +    QTest::newRow("multiversion 2")
 +        << "import com.nokia.Test 1.11\n"
 +           "import com.nokia.Test 1.12\n"
 +           "OldTest {}"
 +        << (!qmlCheckTypes()?"TestType":"")
 +        << (!qmlCheckTypes()?"":"OldTest is ambiguous. Found in com/nokia/Test in version 1.12 and 1.11");
 +    QTest::newRow("qualified multiversion 3")
 +        << "import com.nokia.Test 1.0 as T0\n"
 +           "import com.nokia.Test 1.8 as T8\n"
 +           "T0.Test {}"
 +        << "TestType"
 +        << "";
 +    QTest::newRow("qualified multiversion 4")
 +        << "import com.nokia.Test 1.0 as T0\n"
 +           "import com.nokia.Test 1.8 as T8\n"
 +           "T8.Test {}"
 +        << "TestType2"
 +        << "";
 +}
 +
 +void tst_qqmllanguage::importsBuiltin()
 +{
 +    QFETCH(QString, qml);
 +    QFETCH(QString, type);
 +    QFETCH(QString, error);
 +    testType(qml,type,error);
 +}
 +
 +void tst_qqmllanguage::importsLocal_data()
 +{
 +    QTest::addColumn<QString>("qml");
 +    QTest::addColumn<QString>("type");
 +    QTest::addColumn<QString>("error");
 +
 +    // import locals
 +    QTest::newRow("local import")
 +        << "import \"subdir\"\n" // QT-613
 +           "Test {}"
 +        << "QQuickRectangle"
 +        << "";
 +    QTest::newRow("local import second")
 +        << "import QtQuick 2.0\nimport \"subdir\"\n"
 +           "Test {}"
 +        << "QQuickRectangle"
 +        << "";
 +    QTest::newRow("local import subsubdir")
 +        << "import QtQuick 2.0\nimport \"subdir/subsubdir\"\n"
 +           "SubTest {}"
 +        << "QQuickRectangle"
 +        << "";
 +    QTest::newRow("local import QTBUG-7721 A")
 +        << "subdir.Test {}" // no longer allowed (QTBUG-7721)
 +        << ""
 +        << "subdir.Test - subdir is not a namespace";
 +    QTest::newRow("local import QTBUG-7721 B")
 +        << "import \"subdir\" as X\n"
 +           "X.subsubdir.SubTest {}" // no longer allowed (QTBUG-7721)
 +        << ""
 +        << "X.subsubdir.SubTest - nested namespaces not allowed";
 +    QTest::newRow("local import as")
 +        << "import \"subdir\" as T\n"
 +           "T.Test {}"
 +        << "QQuickRectangle"
 +        << "";
 +    QTest::newRow("wrong local import as")
 +        << "import \"subdir\" as T\n"
 +           "Test {}"
 +        << ""
 +        << "Test is not a type";
 +    QTest::newRow("library precedence over local import")
 +        << "import \"subdir\"\n"
 +           "import com.nokia.Test 1.0\n"
 +           "Test {}"
 +        << (!qmlCheckTypes()?"TestType":"")
 +        << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test and in subdir");
 +}
 +
 +void tst_qqmllanguage::importsLocal()
 +{
 +    QFETCH(QString, qml);
 +    QFETCH(QString, type);
 +    QFETCH(QString, error);
 +    testType(qml,type,error);
 +}
 +
 +void tst_qqmllanguage::basicRemote_data()
 +{
 +    QTest::addColumn<QUrl>("url");
 +    QTest::addColumn<QString>("type");
 +    QTest::addColumn<QString>("error");
 +
 +    QString serverdir = "http://127.0.0.1:14447/qtest/qml/qqmllanguage/";
 +
 +    QTest::newRow("no need for qmldir") << QUrl(serverdir+"Test.qml") << "" << "";
 +    QTest::newRow("absent qmldir") << QUrl(serverdir+"/noqmldir/Test.qml") << "" << "";
 +    QTest::newRow("need qmldir") << QUrl(serverdir+"TestLocal.qml") << "" << "";
 +}
 +
 +void tst_qqmllanguage::basicRemote()
 +{
 +    QFETCH(QUrl, url);
 +    QFETCH(QString, type);
 +    QFETCH(QString, error);
 +
 +    TestHTTPServer server(14447);
 +    server.serveDirectory(testdata());
 +
 +    QQmlComponent component(&engine, url);
 +
 +    QTRY_VERIFY(!component.isLoading());
 +
 +    if (error.isEmpty()) {
 +        if (component.isError())
 +            qDebug() << component.errors();
 +        QVERIFY(!component.isError());
 +    } else {
 +        QVERIFY(component.isError());
 +    }
 +}
 +
 +void tst_qqmllanguage::importsRemote_data()
 +{
 +    QTest::addColumn<QString>("qml");
 +    QTest::addColumn<QString>("type");
 +    QTest::addColumn<QString>("error");
 +
 +    QString serverdir = "http://127.0.0.1:14447/qtest/qml/qqmllanguage";
 +
 +    QTest::newRow("remote import") << "import \""+serverdir+"\"\nTest {}" << "QQuickRectangle"
 +        << "";
 +    QTest::newRow("remote import with subdir") << "import \""+serverdir+"\"\nTestSubDir {}" << "QQuickText"
 +        << "";
 +    QTest::newRow("remote import with local") << "import \""+serverdir+"\"\nTestLocal {}" << "QQuickImage"
 +        << "";
 +    QTest::newRow("wrong remote import with undeclared local") << "import \""+serverdir+"\"\nWrongTestLocal {}" << ""
 +        << "WrongTestLocal is not a type";
 +    QTest::newRow("wrong remote import of internal local") << "import \""+serverdir+"\"\nLocalInternal {}" << ""
 +        << "LocalInternal is not a type";
 +    QTest::newRow("wrong remote import of undeclared local") << "import \""+serverdir+"\"\nUndeclaredLocal {}" << ""
 +        << "UndeclaredLocal is not a type";
 +}
 +
 +void tst_qqmllanguage::importsRemote()
 +{
 +    QFETCH(QString, qml);
 +    QFETCH(QString, type);
 +    QFETCH(QString, error);
 +
 +    TestHTTPServer server(14447);
 +    server.serveDirectory(testdata());
 +
 +    testType(qml,type,error);
 +}
 +
 +void tst_qqmllanguage::importsInstalled_data()
 +{
 +    // QT-610
 +
 +    QTest::addColumn<QString>("qml");
 +    QTest::addColumn<QString>("type");
 +    QTest::addColumn<QString>("error");
 +
 +    // import installed
 +    QTest::newRow("installed import 0")
 +        << "import com.nokia.installedtest0 0.0\n"
 +           "InstalledTestTP {}"
 +        << "QQuickRectangle"
 +        << "";
 +    QTest::newRow("installed import 0 as TP")
 +        << "import com.nokia.installedtest0 0.0 as TP\n"
 +           "TP.InstalledTestTP {}"
 +        << "QQuickRectangle"
 +        << "";
 +    QTest::newRow("installed import 1")
 +        << "import com.nokia.installedtest 1.0\n"
 +           "InstalledTest {}"
 +        << "QQuickRectangle"
 +        << "";
 +    QTest::newRow("installed import 2")
 +        << "import com.nokia.installedtest 1.3\n"
 +           "InstalledTest {}"
 +        << "QQuickRectangle"
 +        << "";
 +    QTest::newRow("installed import 3")
 +        << "import com.nokia.installedtest 1.4\n"
 +           "InstalledTest {}"
 +        << "QQuickText"
 +        << "";
 +    QTest::newRow("installed import minor version not available") // QTBUG-11936
 +        << "import com.nokia.installedtest 0.1\n"
 +           "InstalledTest {}"
 +        << ""
 +        << "module \"com.nokia.installedtest\" version 0.1 is not installed";
 +    QTest::newRow("installed import minor version not available") // QTBUG-9627
 +        << "import com.nokia.installedtest 1.10\n"
 +           "InstalledTest {}"
 +        << ""
 +        << "module \"com.nokia.installedtest\" version 1.10 is not installed";
 +    QTest::newRow("installed import major version not available") // QTBUG-9627
 +        << "import com.nokia.installedtest 9.0\n"
 +           "InstalledTest {}"
 +        << ""
 +        << "module \"com.nokia.installedtest\" version 9.0 is not installed";
 +    QTest::newRow("installed import visibility") // QT-614
 +        << "import com.nokia.installedtest 1.4\n"
 +           "PrivateType {}"
 +        << ""
 +        << "PrivateType is not a type";
 +}
 +
 +void tst_qqmllanguage::importsInstalled()
 +{
 +    QFETCH(QString, qml);
 +    QFETCH(QString, type);
 +    QFETCH(QString, error);
 +    testType(qml,type,error);
 +}
 +
 +
 +void tst_qqmllanguage::importsOrder_data()
 +{
 +    QTest::addColumn<QString>("qml");
 +    QTest::addColumn<QString>("type");
 +    QTest::addColumn<QString>("error");
 +
 +    QTest::newRow("double import") <<
 +           "import com.nokia.installedtest 1.4\n"
 +           "import com.nokia.installedtest 1.4\n"
 +           "InstalledTest {}"
 +           << (!qmlCheckTypes()?"QQuickText":"")
 +           << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.4");
 +    QTest::newRow("installed import overrides 1") <<
 +           "import com.nokia.installedtest 1.0\n"
 +           "import com.nokia.installedtest 1.4\n"
 +           "InstalledTest {}"
 +           << (!qmlCheckTypes()?"QQuickText":"")
 +           << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.0");
 +    QTest::newRow("installed import overrides 2") <<
 +           "import com.nokia.installedtest 1.4\n"
 +           "import com.nokia.installedtest 1.0\n"
 +           "InstalledTest {}"
 +           << (!qmlCheckTypes()?"QQuickRectangle":"")
 +           << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.0 and 1.4");
 +    QTest::newRow("installed import re-overrides 1") <<
 +           "import com.nokia.installedtest 1.4\n"
 +           "import com.nokia.installedtest 1.0\n"
 +           "import com.nokia.installedtest 1.4\n"
 +           "InstalledTest {}"
 +           << (!qmlCheckTypes()?"QQuickText":"")
 +           << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.0");
 +    QTest::newRow("installed import re-overrides 2") <<
 +           "import com.nokia.installedtest 1.4\n"
 +           "import com.nokia.installedtest 1.0\n"
 +           "import com.nokia.installedtest 1.4\n"
 +           "import com.nokia.installedtest 1.0\n"
 +           "InstalledTest {}"
 +           << (!qmlCheckTypes()?"QQuickRectangle":"")
 +           << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.0 and 1.4");
 +
 +    QTest::newRow("installed import versus builtin 1") <<
 +           "import com.nokia.installedtest 1.5\n"
 +           "import QtQuick 2.0\n"
 +           "Rectangle {}"
 +           << (!qmlCheckTypes()?"QQuickRectangle":"")
 +           << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in Qt and in lib/com/nokia/installedtest");
 +    QTest::newRow("installed import versus builtin 2") <<
 +           "import QtQuick 2.0\n"
 +           "import com.nokia.installedtest 1.5\n"
 +           "Rectangle {}"
 +           << (!qmlCheckTypes()?"QQuickText":"")
 +           << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in lib/com/nokia/installedtest and in Qt");
 +    QTest::newRow("namespaces cannot be overridden by types 1") <<
 +           "import QtQuick 2.0 as Rectangle\n"
 +           "import com.nokia.installedtest 1.5\n"
 +           "Rectangle {}"
 +        << ""
 +        << "Namespace Rectangle cannot be used as a type";
 +    QTest::newRow("namespaces cannot be overridden by types 2") <<
 +           "import QtQuick 2.0 as Rectangle\n"
 +           "import com.nokia.installedtest 1.5\n"
 +           "Rectangle.Image {}"
 +        << "QQuickImage"
 +        << "";
 +    QTest::newRow("local last 1") <<
 +           "LocalLast {}"
 +        << "QQuickText"
 +        << "";
 +    QTest::newRow("local last 2") <<
 +           "import com.nokia.installedtest 1.0\n"
 +           "LocalLast {}"
 +           << (!qmlCheckTypes()?"QQuickRectangle":"")// i.e. from com.nokia.installedtest, not data/LocalLast.qml
 +           << (!qmlCheckTypes()?"":"LocalLast is ambiguous. Found in lib/com/nokia/installedtest and in local directory");
 +}
 +
 +void tst_qqmllanguage::importsOrder()
 +{
 +    QFETCH(QString, qml);
 +    QFETCH(QString, type);
 +    QFETCH(QString, error);
 +    testType(qml,type,error);
 +}
 +
 +void tst_qqmllanguage::importIncorrectCase()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("importIncorrectCase.qml"));
 +
 +    QList<QQmlError> errors = component.errors();
 +    QCOMPARE(errors.count(), 1);
 +
 +#if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
 +    QString expectedError = QLatin1String("cannot load module \"com.Nokia.installedtest\": File name case mismatch for \"") + testdata("lib/com/Nokia/installedtest/qmldir") + QLatin1String("\"");
 +#else
 +    QString expectedError = QLatin1String("module \"com.Nokia.installedtest\" is not installed");
 +#endif
 +
 +    QCOMPARE(errors.at(0).description(), expectedError);
 +}
 +
 +void tst_qqmllanguage::importJs_data()
 +{
 +    QTest::addColumn<QString>("file");
 +    QTest::addColumn<QString>("errorFile");
 +    QTest::addColumn<bool>("performTest");
 +
 +    QTest::newRow("defaultVersion")
 +        << "importJs.1.qml"
 +        << "importJs.1.errors.txt"
 +        << true;
 +
 +    QTest::newRow("specifiedVersion")
 +        << "importJs.2.qml"
 +        << "importJs.2.errors.txt"
 +        << true;
 +
 +    QTest::newRow("excludeExcessiveVersion")
 +        << "importJs.3.qml"
 +        << "importJs.3.errors.txt"
 +        << false;
 +
 +    QTest::newRow("includeAppropriateVersion")
 +        << "importJs.4.qml"
 +        << "importJs.4.errors.txt"
 +        << true;
 +
 +    QTest::newRow("noDefaultVersion")
 +        << "importJs.5.qml"
 +        << "importJs.5.errors.txt"
 +        << false;
 +
 +    QTest::newRow("repeatImportFails")
 +        << "importJs.6.qml"
 +        << "importJs.6.errors.txt"
 +        << false;
 +
 +    QTest::newRow("multipleVersionImportFails")
 +        << "importJs.7.qml"
 +        << "importJs.7.errors.txt"
 +        << false;
 +
 +    QTest::newRow("namespacedImport")
 +        << "importJs.8.qml"
 +        << "importJs.8.errors.txt"
 +        << true;
 +
 +    QTest::newRow("namespacedVersionedImport")
 +        << "importJs.9.qml"
 +        << "importJs.9.errors.txt"
 +        << true;
 +
 +    QTest::newRow("namespacedRepeatImport")
 +        << "importJs.10.qml"
 +        << "importJs.10.errors.txt"
 +        << true;
 +}
 +
 +void tst_qqmllanguage::importJs()
 +{
 +    QFETCH(QString, file);
 +    QFETCH(QString, errorFile);
 +    QFETCH(bool, performTest);
 +
 +    QQmlComponent component(&engine, TEST_FILE(file));
 +
 +    {
 +        DETERMINE_ERRORS(errorFile.toLatin1().constData(),expected,actual);
 +        QCOMPARE(expected.size(), actual.size());
 +        for (int i = 0; i < expected.size(); ++i)
 +        {
 +            size_t compareLen = std::min(expected.at(i).length(), actual.at(i).length());
 +            QCOMPARE(expected.at(i).left(compareLen), actual.at(i).left(compareLen));
 +        }
 +    }
 +
 +    if (performTest) {
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +        QCOMPARE(object->property("test").toBool(),true);
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmllanguage::qmlAttachedPropertiesObjectMethod()
 +{
 +    QObject object;
 +
 +    QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, false), (QObject *)0);
 +    QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(&object, true), (QObject *)0);
 +
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.1.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(qmlAttachedPropertiesObject<MyQmlObject>(object, false), (QObject *)0);
 +        QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.2.qml"));
 +        VERIFY_ERRORS(0);
 +        QObject *object = component.create();
 +        QVERIFY(object != 0);
 +
 +        QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, false) != 0);
 +        QVERIFY(qmlAttachedPropertiesObject<MyQmlObject>(object, true) != 0);
 +    }
 +}
 +
 +void tst_qqmllanguage::crash1()
 +{
 +    QQmlComponent component(&engine);
 +    component.setData("import QtQuick 2.0\nComponent {}", QUrl());
 +}
 +
 +void tst_qqmllanguage::crash2()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("crash2.qml"));
 +}
 +
 +// QTBUG-8676
 +void tst_qqmllanguage::customOnProperty()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("customOnProperty.qml"));
 +
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("on").toInt(), 10);
 +
 +    delete object;
 +}
 +
 +// QTBUG-12601
 +void tst_qqmllanguage::variantNotify()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("variantNotify.qml"));
 +
 +    VERIFY_ERRORS(0);
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("notifyCount").toInt(), 1);
 +
 +    delete object;
 +}
 +
 +void tst_qqmllanguage::revisions()
 +{
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("revisions11.qml"));
 +
 +        VERIFY_ERRORS(0);
 +        MyRevisionedClass *object = qobject_cast<MyRevisionedClass*>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->prop2(), 10.0);
 +
 +        delete object;
 +    }
 +    {
 +        QQmlEngine myEngine;
 +        QQmlComponent component(&myEngine, TEST_FILE("revisionssub11.qml"));
 +
 +        VERIFY_ERRORS(0);
 +        MyRevisionedSubclass *object = qobject_cast<MyRevisionedSubclass*>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->prop1(), 10.0);
 +        QCOMPARE(object->prop2(), 10.0);
 +        QCOMPARE(object->prop3(), 10.0);
 +        QCOMPARE(object->prop4(), 10.0);
 +
 +        delete object;
 +    }
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("versionedbase.qml"));
 +        VERIFY_ERRORS(0);
 +        MySubclass *object = qobject_cast<MySubclass*>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->prop1(), 10.0);
 +        QCOMPARE(object->prop2(), 10.0);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmllanguage::revisionOverloads()
 +{
 +    {
 +    QQmlComponent component(&engine, TEST_FILE("allowedRevisionOverloads.qml"));
 +    VERIFY_ERRORS(0);
 +    }
 +    {
 +    QQmlComponent component(&engine, TEST_FILE("disallowedRevisionOverloads.qml"));
 +    QEXPECT_FAIL("", "QTBUG-13849", Abort);
 +    QVERIFY(0);
 +    VERIFY_ERRORS("disallowedRevisionOverloads.errors.txt");
 +    }
 +}
 +
 +void tst_qqmllanguage::initTestCase()
 +{
 +    QString testdataDir = QFileInfo(QFINDTESTDATA("data")).absolutePath();
 +    QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir));
 +
 +    registerTypes();
 +
 +    // Registering the TestType class in other modules should have no adverse effects
 +    qmlRegisterType<TestType>("com.nokia.TestPre", 1, 0, "Test");
 +
 +    qmlRegisterType<TestType>("com.nokia.Test", 0, 0, "TestTP");
 +    qmlRegisterType<TestType>("com.nokia.Test", 1, 0, "Test");
 +    qmlRegisterType<TestType>("com.nokia.Test", 1, 5, "Test");
 +    qmlRegisterType<TestType2>("com.nokia.Test", 1, 8, "Test");
 +    qmlRegisterType<TestType>("com.nokia.Test", 1, 9, "OldTest");
 +    qmlRegisterType<TestType2>("com.nokia.Test", 1, 12, "Test");
 +
 +    // Registering the TestType class in other modules should have no adverse effects
 +    qmlRegisterType<TestType>("com.nokia.TestPost", 1, 0, "Test");
 +
 +    // Create locale-specific file
 +    // For POSIX, this will just be data/I18nType.qml, since POSIX is 7-bit
 +    // For iso8859-1 locale, this will just be data/I18nType?????.qml where ????? is 5 8-bit characters
 +    // For utf-8 locale, this will be data/I18nType??????????.qml where ?????????? is 5 8-bit characters, UTF-8 encoded
 +    QFile in(TEST_FILE(QLatin1String("I18nType30.qml")).toLocalFile());
 +    QVERIFY2(in.open(QIODevice::ReadOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(in.fileName(), in.errorString())));
 +    QFile out(TEST_FILE(QString::fromUtf8("I18nType\303\201\303\242\303\243\303\244\303\245.qml")).toLocalFile());
 +    QVERIFY2(out.open(QIODevice::WriteOnly), qPrintable(QString::fromLatin1("Cannot open '%1': %2").arg(out.fileName(), out.errorString())));
 +    out.write(in.readAll());
 +}
 +
 +void tst_qqmllanguage::aliasPropertyChangeSignals()
 +{
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.qml"));
 +
 +        VERIFY_ERRORS(0);
 +        QObject *o = component.create();
 +        QVERIFY(o != 0);
 +
 +        QCOMPARE(o->property("test").toBool(), true);
 +
 +        delete o;
 +    }
 +
 +    // QTCREATORBUG-2769
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("aliasPropertyChangeSignals.2.qml"));
 +
 +        VERIFY_ERRORS(0);
 +        QObject *o = component.create();
 +        QVERIFY(o != 0);
 +
 +        QCOMPARE(o->property("test").toBool(), true);
 +
 +        delete o;
 +    }
 +}
 +
 +// Tests property initializers
 +void tst_qqmllanguage::propertyInit()
 +{
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("propertyInit.1.qml"));
 +
 +        VERIFY_ERRORS(0);
 +        QObject *o = component.create();
 +        QVERIFY(o != 0);
 +
 +        QCOMPARE(o->property("test").toInt(), 1);
 +
 +        delete o;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, TEST_FILE("propertyInit.2.qml"));
 +
 +        VERIFY_ERRORS(0);
 +        QObject *o = component.create();
 +        QVERIFY(o != 0);
 +
 +        QCOMPARE(o->property("test").toInt(), 123);
 +
 +        delete o;
 +    }
 +}
 +
 +// Test that registration order doesn't break type availability
 +// QTBUG-16878
 +void tst_qqmllanguage::registrationOrder()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("registrationOrder.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QVERIFY(o->metaObject() == &MyVersion2Class::staticMetaObject);
 +    delete o;
 +}
 +
 +void tst_qqmllanguage::readonly()
 +{
 +    QQmlComponent component(&engine, TEST_FILE("readonly.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test1").toInt(), 10);
 +    QCOMPARE(o->property("test2").toInt(), 18);
 +    QCOMPARE(o->property("test3").toInt(), 13);
 +
 +    o->setProperty("testData", 13);
 +
 +    QCOMPARE(o->property("test1").toInt(), 10);
 +    QCOMPARE(o->property("test2").toInt(), 22);
 +    QCOMPARE(o->property("test3").toInt(), 13);
 +
 +    o->setProperty("testData2", 2);
 +
 +    QCOMPARE(o->property("test1").toInt(), 10);
 +    QCOMPARE(o->property("test2").toInt(), 22);
 +    QCOMPARE(o->property("test3").toInt(), 2);
 +
 +    o->setProperty("test1", 11);
 +    o->setProperty("test2", 11);
 +    o->setProperty("test3", 11);
 +
 +    QCOMPARE(o->property("test1").toInt(), 10);
 +    QCOMPARE(o->property("test2").toInt(), 22);
 +    QCOMPARE(o->property("test3").toInt(), 2);
 +
 +    delete o;
 +}
 +
 +// QTBUG-18268
 +void tst_qqmllanguage::remoteLoadCrash()
 +{
 +    TestHTTPServer server(14448);
 +    server.serveDirectory(testdata());
 +
 +    QQmlComponent component(&engine);
 +    component.setData("import QtQuick 2.0; Text {}", QUrl("http://127.0.0.1:14448/remoteLoadCrash.qml"));
 +    while (component.isLoading()) 
 +        QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents, 50);
 +
 +    QObject *o = component.create();
 +    delete o;
 +}
 +
 +QTEST_MAIN(tst_qqmllanguage)
 +
 +#include "tst_qqmllanguage.moc"
index af1a818,0000000..46435fb
mode 100644,000000..100644
--- /dev/null
@@@ -1,1183 -1,0 +1,1219 @@@
-         LOCALE_PROP(int,firstDayOfWeek),
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <qtest.h>
 +#include <QDebug>
 +
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtCore/QDateTime>
 +#include <qcolor.h>
 +#include "../../shared/util.h"
 +
 +class tst_qqmllocale : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_qqmllocale() { }
 +
 +private slots:
 +    void defaultLocale();
 +
 +    void properties_data();
 +    void properties();
 +    void currencySymbol_data();
 +    void currencySymbol();
 +    void monthName_data();
 +    void monthName();
 +    void standaloneMonthName_data();
 +    void standaloneMonthName();
 +    void dayName_data();
 +    void dayName();
 +    void standaloneDayName_data();
 +    void standaloneDayName();
++    void firstDayOfWeek_data();
++    void firstDayOfWeek();
 +    void weekDays_data();
 +    void weekDays();
 +    void uiLanguages_data();
 +    void uiLanguages();
 +    void dateFormat_data();
 +    void dateFormat();
 +    void dateTimeFormat_data();
 +    void dateTimeFormat();
 +    void timeFormat_data();
 +    void timeFormat();
 +
 +    void dateToLocaleString_data();
 +    void dateToLocaleString();
 +    void dateToLocaleStringFormatted_data();
 +    void dateToLocaleStringFormatted();
 +    void dateToLocaleDateString_data();
 +    void dateToLocaleDateString();
 +    void dateToLocaleDateStringFormatted_data();
 +    void dateToLocaleDateStringFormatted();
 +    void dateToLocaleTimeString_data();
 +    void dateToLocaleTimeString();
 +    void dateToLocaleTimeStringFormatted_data();
 +    void dateToLocaleTimeStringFormatted();
 +    void dateFromLocaleString_data();
 +    void dateFromLocaleString();
 +    void dateFromLocaleDateString_data();
 +    void dateFromLocaleDateString();
 +    void dateFromLocaleTimeString_data();
 +    void dateFromLocaleTimeString();
 +
 +    void numberToLocaleString_data();
 +    void numberToLocaleString();
 +    void numberToLocaleCurrencyString_data();
 +    void numberToLocaleCurrencyString();
 +    void numberFromLocaleString_data();
 +    void numberFromLocaleString();
 +    void numberConstToLocaleString();
 +
 +    void stringLocaleCompare_data();
 +    void stringLocaleCompare();
 +
 +private:
 +    void addPropertyData(const QString &l);
 +    QVariant getProperty(QObject *obj, const QString &locale, const QString &property);
 +    void addCurrencySymbolData(const QString &locale);
 +    void addStandardFormatData();
 +    void addFormatNameData(const QString &locale);
 +    void addDateTimeFormatData(const QString &l);
 +    void addDateFormatData(const QString &l);
 +    void addTimeFormatData(const QString &l);
 +    QQmlEngine engine;
 +};
 +
 +void tst_qqmllocale::defaultLocale()
 +{
 +    QQmlComponent c(&engine, testFileUrl("properties.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QCOMPARE(obj->property("name").toString(), QLocale().name());
 +}
 +
 +#define LOCALE_PROP(type,prop) { #prop, QVariant(type(qlocale.prop())) }
 +
 +void tst_qqmllocale::addPropertyData(const QString &l)
 +{
 +    QLocale qlocale(l);
 +
 +    struct {
 +        const char *name;
 +        QVariant value;
 +    }
 +    values[] = {
 +        LOCALE_PROP(QString,name),
 +        LOCALE_PROP(QString,amText),
 +        LOCALE_PROP(QString,pmText),
 +        LOCALE_PROP(QString,nativeLanguageName),
 +        LOCALE_PROP(QString,nativeCountryName),
 +        LOCALE_PROP(QString,decimalPoint),
 +        LOCALE_PROP(QString,groupSeparator),
 +        LOCALE_PROP(QString,percent),
 +        LOCALE_PROP(QString,zeroDigit),
 +        LOCALE_PROP(QString,negativeSign),
 +        LOCALE_PROP(QString,positiveSign),
 +        LOCALE_PROP(QString,exponential),
 +        LOCALE_PROP(int,measurementSystem),
 +        LOCALE_PROP(int,textDirection),
 +        { 0, QVariant() }
 +    };
 +
 +    int i = 0;
 +    while (values[i].name) {
 +        QByteArray n = l.toLatin1() + ':' + values[i].name;
 +        QTest::newRow(n.constData()) << l << QByteArray(values[i].name) << values[i].value;
 +        ++i;
 +    }
 +}
 +
 +void tst_qqmllocale::properties_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<QByteArray>("property");
 +    QTest::addColumn<QVariant>("value");
 +
 +    addPropertyData("en_US");
 +    addPropertyData("de_DE");
 +    addPropertyData("ar_SA");
 +    addPropertyData("hi_IN");
 +    addPropertyData("zh_CN");
 +    addPropertyData("th_TH");
 +}
 +
 +void tst_qqmllocale::properties()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(QByteArray, property);
 +    QFETCH(QVariant, value);
 +
 +    QQmlComponent c(&engine, testFileUrl("properties.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QCOMPARE(obj->property(property), value);
 +
 +    delete obj;
 +}
 +
 +void tst_qqmllocale::addCurrencySymbolData(const QString &l)
 +{
 +    QByteArray locale = l.toLatin1();
 +    QTest::newRow(locale.constData()) << l << -1;
 +    QByteArray t(locale);
 +    t += " CurrencyIsoCode";
 +    QTest::newRow(t.constData()) << l << (int)QLocale::CurrencyIsoCode;
 +    t = locale + " CurrencySymbol";
 +    QTest::newRow(t.constData()) << l << (int)QLocale::CurrencySymbol;
 +    t = locale + " CurrencyDisplayName";
 +    QTest::newRow(t.constData()) << l << (int)QLocale::CurrencyDisplayName;
 +}
 +
 +void tst_qqmllocale::currencySymbol_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<int>("param");
 +
 +    addCurrencySymbolData("en_US");
 +    addCurrencySymbolData("de_DE");
 +    addCurrencySymbolData("ar_SA");
 +    addCurrencySymbolData("hi_IN");
 +    addCurrencySymbolData("zh_CN");
 +    addCurrencySymbolData("th_TH");
 +}
 +
 +void tst_qqmllocale::currencySymbol()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("functions.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QLocale l(locale);
 +    QVariant val;
 +    QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol;
 +
 +    if (param >= 0)
 +        format = QLocale::CurrencySymbolFormat(param);
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QMetaObject::invokeMethod(obj, "currencySymbol", Qt::DirectConnection,
 +            Q_RETURN_ARG(QVariant, val),
 +            Q_ARG(QVariant, QVariant(int(format))));
 +
 +    QCOMPARE(val.toString(), l.currencySymbol(format));
 +
 +    delete obj;
 +}
 +
 +void tst_qqmllocale::addFormatNameData(const QString &l)
 +{
 +    QByteArray locale = l.toLatin1();
 +    QTest::newRow(locale.constData()) << l << -1;
 +    QByteArray t(locale);
 +    t += " LongFormat";
 +    QTest::newRow(t.constData()) << l << (int)QLocale::LongFormat;
 +    t = locale + " ShortFormat";
 +    QTest::newRow(t.constData()) << l << (int)QLocale::ShortFormat;
 +    t = locale + " NarrowFormat";
 +    QTest::newRow(t.constData()) << l << (int)QLocale::NarrowFormat;
 +}
 +
 +void tst_qqmllocale::addStandardFormatData()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<int>("param");
 +
 +    addFormatNameData("en_US");
 +    addFormatNameData("de_DE");
 +    addFormatNameData("ar_SA");
 +    addFormatNameData("hi_IN");
 +    addFormatNameData("zh_CN");
 +    addFormatNameData("th_TH");
 +}
 +
 +void tst_qqmllocale::monthName_data()
 +{
 +    addStandardFormatData();
 +}
 +
 +void tst_qqmllocale::monthName()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("functions.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QLocale l(locale);
 +    QVariant val;
 +    QLocale::FormatType format = QLocale::LongFormat;
 +    if (param >= 0)
 +        format = QLocale::FormatType(param);
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    for (int i = 0; i <= 11; ++i) {
 +        QMetaObject::invokeMethod(obj, "monthName", Qt::DirectConnection,
 +            Q_RETURN_ARG(QVariant, val),
 +            Q_ARG(QVariant, QVariant(i)),
 +            Q_ARG(QVariant, QVariant(int(format))));
 +
 +        // QLocale January == 1, JS Date January == 0
 +        QCOMPARE(val.toString(), l.monthName(i+1, format));
 +    }
 +
 +    delete obj;
 +}
 +
 +void tst_qqmllocale::standaloneMonthName_data()
 +{
 +    addStandardFormatData();
 +}
 +
 +void tst_qqmllocale::standaloneMonthName()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("functions.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QLocale l(locale);
 +    QVariant val;
 +    QLocale::FormatType format = QLocale::LongFormat;
 +    if (param >= 0)
 +        format = QLocale::FormatType(param);
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    for (int i = 0; i <= 11; ++i) {
 +        QMetaObject::invokeMethod(obj, "standaloneMonthName", Qt::DirectConnection,
 +            Q_RETURN_ARG(QVariant, val),
 +            Q_ARG(QVariant, QVariant(i)),
 +            Q_ARG(QVariant, QVariant(int(format))));
 +
 +        // QLocale January == 1, JS Date January == 0
 +        QCOMPARE(val.toString(), l.standaloneMonthName(i+1, format));
 +    }
 +
 +    delete obj;
 +}
 +
 +void tst_qqmllocale::dayName_data()
 +{
 +    addStandardFormatData();
 +}
 +
 +void tst_qqmllocale::dayName()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("functions.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QLocale l(locale);
 +    QVariant val;
 +    QLocale::FormatType format = QLocale::LongFormat;
 +    if (param >= 0)
 +        format = QLocale::FormatType(param);
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    for (int i = 1; i <= 7; ++i) {
 +        QMetaObject::invokeMethod(obj, "dayName", Qt::DirectConnection,
 +            Q_RETURN_ARG(QVariant, val),
 +            Q_ARG(QVariant, QVariant(i)),
 +            Q_ARG(QVariant, QVariant(int(format))));
 +
 +        QCOMPARE(val.toString(), l.dayName(i, format));
 +    }
 +
 +    delete obj;
 +}
 +
 +void tst_qqmllocale::standaloneDayName_data()
 +{
 +    addStandardFormatData();
 +}
 +
 +void tst_qqmllocale::standaloneDayName()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("functions.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QLocale l(locale);
 +    QVariant val;
 +    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    for (int i = 1; i <= 7; ++i) {
 +        QMetaObject::invokeMethod(obj, "standaloneDayName", Qt::DirectConnection,
 +                Q_RETURN_ARG(QVariant, val),
 +                Q_ARG(QVariant, QVariant(i)),
 +                Q_ARG(QVariant, QVariant(int(format))));
 +
 +        QCOMPARE(val.toString(), l.standaloneDayName(i, format));
 +    }
 +
 +    delete obj;
 +}
 +
++void tst_qqmllocale::firstDayOfWeek_data()
++{
++    QTest::addColumn<QString>("locale");
++
++    QTest::newRow("en_US") << "en_US";
++    QTest::newRow("de_DE") << "de_DE";
++    QTest::newRow("ar_SA") << "ar_SA";
++    QTest::newRow("hi_IN") << "hi_IN";
++    QTest::newRow("zh_CN") << "zh_CN";
++    QTest::newRow("th_TH") << "th_TH";
++}
++
++void tst_qqmllocale::firstDayOfWeek()
++{
++    QFETCH(QString, locale);
++
++    QQmlComponent c(&engine, testFileUrl("properties.qml"));
++
++    QObject *obj = c.create();
++    QVERIFY(obj);
++
++    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
++        Q_ARG(QVariant, QVariant(locale)));
++
++    QVariant val = obj->property("firstDayOfWeek");
++    QVERIFY(val.type() == QVariant::Int);
++
++    int day = int(QLocale(locale).firstDayOfWeek());
++    if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
++        day = 0;
++    QCOMPARE(day, val.toInt());
++
++    delete obj;
++}
++
 +void tst_qqmllocale::weekDays_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +
 +    QTest::newRow("en_US") << "en_US";
 +    QTest::newRow("de_DE") << "de_DE";
 +    QTest::newRow("ar_SA") << "ar_SA";
 +    QTest::newRow("hi_IN") << "hi_IN";
 +    QTest::newRow("zh_CN") << "zh_CN";
 +    QTest::newRow("th_TH") << "th_TH";
 +}
 +
 +void tst_qqmllocale::weekDays()
 +{
 +    QFETCH(QString, locale);
 +
 +    QQmlComponent c(&engine, testFileUrl("properties.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QVariant val = obj->property("weekDays");
 +    QVERIFY(val.type() == QVariant::List);
 +
 +    QList<QVariant> qmlDays = val.toList();
 +    QList<Qt::DayOfWeek> days = QLocale(locale).weekdays();
 +
 +    QVERIFY(days.count() == qmlDays.count());
 +
 +    for (int i = 0; i < days.count(); ++i) {
 +        int day = int(days.at(i));
 +        if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
 +            day = 0;
 +        QCOMPARE(day, qmlDays.at(i).toInt());
 +    }
 +
 +    delete obj;
 +}
 +
 +void tst_qqmllocale::uiLanguages_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +
 +    QTest::newRow("en_US") << "en_US";
 +    QTest::newRow("de_DE") << "de_DE";
 +    QTest::newRow("ar_SA") << "ar_SA";
 +    QTest::newRow("hi_IN") << "hi_IN";
 +    QTest::newRow("zh_CN") << "zh_CN";
 +    QTest::newRow("th_TH") << "th_TH";
 +}
 +
 +void tst_qqmllocale::uiLanguages()
 +{
 +    QFETCH(QString, locale);
 +
 +    QQmlComponent c(&engine, testFileUrl("properties.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QVariant val = obj->property("uiLanguages");
 +    QVERIFY(val.type() == QVariant::List);
 +
 +    QList<QVariant> qmlLangs = val.toList();
 +    QStringList langs = QLocale(locale).uiLanguages();
 +
 +    QVERIFY(langs.count() == qmlLangs.count());
 +
 +    for (int i = 0; i < langs.count(); ++i) {
 +        QCOMPARE(langs.at(i), qmlLangs.at(i).toString());
 +    }
 +
 +    delete obj;
 +}
 +
 +
 +void tst_qqmllocale::dateTimeFormat_data()
 +{
 +    addStandardFormatData();
 +}
 +
 +void tst_qqmllocale::dateTimeFormat()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("functions.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QLocale l(locale);
 +    QVariant val;
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
 +    QMetaObject::invokeMethod(obj, "dateTimeFormat", Qt::DirectConnection,
 +            Q_RETURN_ARG(QVariant, val),
 +            Q_ARG(QVariant, QVariant(param)));
 +
 +    QCOMPARE(val.toString(), l.dateTimeFormat(format));
 +}
 +
 +void tst_qqmllocale::dateFormat_data()
 +{
 +    addStandardFormatData();
 +}
 +
 +void tst_qqmllocale::dateFormat()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("functions.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QLocale l(locale);
 +    QVariant val;
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
 +    QMetaObject::invokeMethod(obj, "dateFormat", Qt::DirectConnection,
 +            Q_RETURN_ARG(QVariant, val),
 +            Q_ARG(QVariant, QVariant(param)));
 +
 +    QCOMPARE(val.toString(), l.dateFormat(format));
 +}
 +
 +void tst_qqmllocale::timeFormat_data()
 +{
 +    addStandardFormatData();
 +}
 +
 +void tst_qqmllocale::timeFormat()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("functions.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QLocale l(locale);
 +    QVariant val;
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
 +    QMetaObject::invokeMethod(obj, "timeFormat", Qt::DirectConnection,
 +            Q_RETURN_ARG(QVariant, val),
 +            Q_ARG(QVariant, QVariant(param)));
 +
 +    QCOMPARE(val.toString(), l.timeFormat(format));
 +}
 +
 +void tst_qqmllocale::dateToLocaleString_data()
 +{
 +    addStandardFormatData();
 +}
 +
 +void tst_qqmllocale::dateToLocaleString()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("date.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QDateTime dt;
 +    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
 +    dt.setTime(QTime(18, 53, 48, 345));
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
 +
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "toLocaleString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(param)));
 +
 +    QLocale l(locale);
 +    QCOMPARE(val.toString(), l.toString(dt, format));
 +}
 +
 +void tst_qqmllocale::addDateTimeFormatData(const QString &l)
 +{
 +    const char *formats[] = {
 +        "hh:mm dd.MM.yyyy",
 +        "h:m:sap ddd MMMM d yy",
 +        "'The date and time is: 'H:mm:ss:zzz dd/MM/yy",
 +        "MMM d yyyy HH:mm t",
 +        0
 +    };
 +    QByteArray locale = l.toLatin1();
 +    int i = 0;
 +    while (formats[i]) {
 +        QByteArray t(locale);
 +        t += " ";
 +        t += formats[i];
 +        QTest::newRow(t.constData()) << l << QString(formats[i]);
 +        ++i;
 +    }
 +}
 +
 +void tst_qqmllocale::dateToLocaleStringFormatted_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<QString>("format");
 +
 +    addDateTimeFormatData("en_US");
 +    addDateTimeFormatData("de_DE");
 +    addDateTimeFormatData("ar_SA");
 +    addDateTimeFormatData("hi_IN");
 +    addDateTimeFormatData("zh_CN");
 +    addDateTimeFormatData("th_TH");
 +}
 +
 +void tst_qqmllocale::dateToLocaleStringFormatted()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(QString, format);
 +
 +    QQmlComponent c(&engine, testFileUrl("date.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QDateTime dt;
 +    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
 +    dt.setTime(QTime(18, 53, 48, 345));
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "toLocaleString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(format)));
 +
 +    QLocale l(locale);
 +    QCOMPARE(val.toString(), l.toString(dt, format));
 +}
 +
 +void tst_qqmllocale::dateToLocaleDateString_data()
 +{
 +    addStandardFormatData();
 +}
 +
 +void tst_qqmllocale::dateToLocaleDateString()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("date.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QDateTime dt;
 +    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
 +    dt.setTime(QTime(18, 53, 48, 345));
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
 +
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "toLocaleDateString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(param)));
 +
 +    QLocale l(locale);
 +    QCOMPARE(val.toString(), l.toString(dt.date(), format));
 +}
 +
 +void tst_qqmllocale::addDateFormatData(const QString &l)
 +{
 +    const char *formats[] = {
 +        "dd.MM.yyyy",
 +        "ddd MMMM d yy",
 +        "'The date is: 'dd/MM/yy",
 +        "MMM d yyyy",
 +        0
 +    };
 +    QByteArray locale = l.toLatin1();
 +    int i = 0;
 +    while (formats[i]) {
 +        QByteArray t(locale);
 +        t += " ";
 +        t += formats[i];
 +        QTest::newRow(t.constData()) << l << QString(formats[i]);
 +        ++i;
 +    }
 +}
 +
 +void tst_qqmllocale::dateToLocaleDateStringFormatted_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<QString>("format");
 +
 +    addDateFormatData("en_US");
 +    addDateFormatData("de_DE");
 +    addDateFormatData("ar_SA");
 +    addDateFormatData("hi_IN");
 +    addDateFormatData("zh_CN");
 +    addDateFormatData("th_TH");
 +}
 +
 +void tst_qqmllocale::dateToLocaleDateStringFormatted()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(QString, format);
 +
 +    QQmlComponent c(&engine, testFileUrl("date.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QDateTime dt;
 +    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
 +    dt.setTime(QTime(18, 53, 48, 345));
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "toLocaleString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(format)));
 +
 +    QLocale l(locale);
 +    QCOMPARE(val.toString(), l.toString(dt.date(), format));
 +}
 +
 +void tst_qqmllocale::dateToLocaleTimeString_data()
 +{
 +    addStandardFormatData();
 +}
 +
 +void tst_qqmllocale::dateToLocaleTimeString()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(int, param);
 +
 +    QQmlComponent c(&engine, testFileUrl("date.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QDateTime dt;
 +    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
 +    dt.setTime(QTime(18, 53, 48, 345));
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param);
 +
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "toLocaleTimeString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(param)));
 +
 +    QLocale l(locale);
 +    QCOMPARE(val.toString(), l.toString(dt.time(), format));
 +}
 +
 +void tst_qqmllocale::addTimeFormatData(const QString &l)
 +{
 +    const char *formats[] = {
 +        "hh:mm",
 +        "h:m:sap",
 +        "'The time is: 'H:mm:ss:zzz",
 +        "HH:mm t",
 +        0
 +    };
 +    QByteArray locale = l.toLatin1();
 +    int i = 0;
 +    while (formats[i]) {
 +        QByteArray t(locale);
 +        t += " ";
 +        t += formats[i];
 +        QTest::newRow(t.constData()) << l << QString(formats[i]);
 +        ++i;
 +    }
 +}
 +
 +void tst_qqmllocale::dateToLocaleTimeStringFormatted_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<QString>("format");
 +
 +    addTimeFormatData("en_US");
 +    addTimeFormatData("de_DE");
 +    addTimeFormatData("ar_SA");
 +    addTimeFormatData("hi_IN");
 +    addTimeFormatData("zh_CN");
 +    addTimeFormatData("th_TH");
 +}
 +
 +void tst_qqmllocale::dateToLocaleTimeStringFormatted()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(QString, format);
 +
 +    QQmlComponent c(&engine, testFileUrl("date.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QDateTime dt;
 +    dt.setDate(QDate(2011, 10, 7)); // weirdly, JS Date month range is 0-11
 +    dt.setTime(QTime(18, 53, 48, 345));
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "toLocaleString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(format)));
 +
 +    QLocale l(locale);
 +    QCOMPARE(val.toString(), l.toString(dt.time(), format));
 +}
 +
 +void tst_qqmllocale::dateFromLocaleString_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<QString>("format");
 +
 +    QTest::newRow("en_US 1") << "en_US" << "dddd, MMMM d, yyyy h:mm:ss AP";
 +    QTest::newRow("en_US long") << "en_US" << QLocale("en_US").dateTimeFormat();
 +    QTest::newRow("en_US short") << "en_US" << QLocale("en_US").dateTimeFormat(QLocale::ShortFormat);
 +    QTest::newRow("de_DE long") << "de_DE" << QLocale("de_DE").dateTimeFormat();
 +    QTest::newRow("de_DE short") << "de_DE" << QLocale("de_DE").dateTimeFormat(QLocale::ShortFormat);
 +    QTest::newRow("ar_SA long") << "ar_SA" << QLocale("ar_SA").dateTimeFormat();
 +    QTest::newRow("ar_SA short") << "ar_SA" << QLocale("ar_SA").dateTimeFormat(QLocale::ShortFormat);
 +    QTest::newRow("zh_CN long") << "zh_CN" << QLocale("zh_CN").dateTimeFormat();
 +    QTest::newRow("zh_CN short") << "zh_CN" << QLocale("zh_CN").dateTimeFormat(QLocale::ShortFormat);
 +}
 +
 +void tst_qqmllocale::dateFromLocaleString()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(QString, format);
 +
 +    QQmlComponent c(&engine, testFileUrl("date.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QDateTime dt;
 +    dt.setDate(QDate(2011, 10, 7));
 +    dt.setTime(QTime(18, 53, 48, 345));
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale l(locale);
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "fromLocaleString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(l.toString(dt, format))),
 +        Q_ARG(QVariant, QVariant(format)));
 +
 +    QDateTime pd = l.toDateTime(l.toString(dt, format), format);
 +    QCOMPARE(val.toDateTime(), pd);
 +}
 +
 +void tst_qqmllocale::dateFromLocaleDateString_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<QString>("format");
 +
 +    QTest::newRow("en_US 1") << "en_US" << "dddd, MMMM d, yyyy h:mm:ss AP";
 +    QTest::newRow("en_US long") << "en_US" << QLocale("en_US").dateTimeFormat();
 +    QTest::newRow("en_US short") << "en_US" << QLocale("en_US").dateTimeFormat(QLocale::ShortFormat);
 +    QTest::newRow("de_DE long") << "de_DE" << QLocale("de_DE").dateTimeFormat();
 +    QTest::newRow("de_DE short") << "de_DE" << QLocale("de_DE").dateTimeFormat(QLocale::ShortFormat);
 +    QTest::newRow("ar_SA long") << "ar_SA" << QLocale("ar_SA").dateTimeFormat();
 +    QTest::newRow("ar_SA short") << "ar_SA" << QLocale("ar_SA").dateTimeFormat(QLocale::ShortFormat);
 +    QTest::newRow("zh_CN long") << "zh_CN" << QLocale("zh_CN").dateTimeFormat();
 +    QTest::newRow("zh_CN short") << "zh_CN" << QLocale("zh_CN").dateTimeFormat(QLocale::ShortFormat);
 +}
 +
 +void tst_qqmllocale::dateFromLocaleDateString()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(QString, format);
 +
 +    QQmlComponent c(&engine, testFileUrl("date.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QDateTime dt;
 +    dt.setDate(QDate(2011, 10, 7));
 +    dt.setTime(QTime(18, 53, 48, 345));
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale l(locale);
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "fromLocaleDateString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(l.toString(dt, format))),
 +        Q_ARG(QVariant, QVariant(format)));
 +
 +    QDate pd = l.toDate(l.toString(dt, format), format);
 +    QCOMPARE(val.toDate(), pd);
 +}
 +
 +void tst_qqmllocale::dateFromLocaleTimeString_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<QString>("format");
 +
 +    QTest::newRow("en_US 1") << "en_US" << "dddd, MMMM d, yyyy h:mm:ss AP";
 +    QTest::newRow("en_US long") << "en_US" << QLocale("en_US").dateTimeFormat();
 +    QTest::newRow("en_US short") << "en_US" << QLocale("en_US").dateTimeFormat(QLocale::ShortFormat);
 +    QTest::newRow("de_DE long") << "de_DE" << QLocale("de_DE").dateTimeFormat();
 +    QTest::newRow("de_DE short") << "de_DE" << QLocale("de_DE").dateTimeFormat(QLocale::ShortFormat);
 +    QTest::newRow("ar_SA long") << "ar_SA" << QLocale("ar_SA").dateTimeFormat();
 +    QTest::newRow("ar_SA short") << "ar_SA" << QLocale("ar_SA").dateTimeFormat(QLocale::ShortFormat);
 +    QTest::newRow("zh_CN long") << "zh_CN" << QLocale("zh_CN").dateTimeFormat();
 +    QTest::newRow("zh_CN short") << "zh_CN" << QLocale("zh_CN").dateTimeFormat(QLocale::ShortFormat);
 +}
 +
 +void tst_qqmllocale::dateFromLocaleTimeString()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(QString, format);
 +
 +    QQmlComponent c(&engine, testFileUrl("date.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QDateTime dt;
 +    dt.setDate(QDate(2011, 10, 7));
 +    dt.setTime(QTime(18, 53, 48, 345));
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale l(locale);
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "fromLocaleTimeString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(l.toString(dt, format))),
 +        Q_ARG(QVariant, QVariant(format)));
 +
 +    QTime pd = l.toTime(l.toString(dt, format), format);
 +    QCOMPARE(val.toTime(), pd);
 +}
 +
 +void tst_qqmllocale::numberToLocaleString_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<char>("format");
 +    QTest::addColumn<int>("prec");
 +
 +    QTest::newRow("en_US 1") << "en_US" << 'f' << 2;
 +    QTest::newRow("en_US 2") << "en_US" << 'g' << 3;
 +    QTest::newRow("en_US 3") << "en_US" << 'f' << 0;
 +    QTest::newRow("en_US 4") << "en_US" << 'f' << -1;
 +    QTest::newRow("de_DE 1") << "de_DE" << 'f' << 2;
 +    QTest::newRow("de_DE 2") << "de_DE" << 'g' << 3;
 +    QTest::newRow("ar_SA 1") << "ar_SA" << 'f' << 2;
 +    QTest::newRow("ar_SA 2") << "ar_SA" << 'g' << 3;
 +}
 +
 +void tst_qqmllocale::numberToLocaleString()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(char, format);
 +    QFETCH(int, prec);
 +
 +    QQmlComponent c(&engine, testFileUrl("number.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    double number = 2344423.3289;
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale l(locale);
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "toLocaleString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(number)),
 +        Q_ARG(QVariant, QVariant(QString(format))),
 +        Q_ARG(QVariant, QVariant(prec)));
 +
 +    if (prec < 0) prec = 2;
 +    QCOMPARE(val.toString(), l.toString(number, format, prec));
 +}
 +
 +void tst_qqmllocale::numberToLocaleCurrencyString_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<QString>("symbol");
 +
 +    QTest::newRow("en_US 1") << "en_US" << QString();
 +    QTest::newRow("en_US 2") << "en_US" << "USD";
 +    QTest::newRow("de_DE") << "de_DE" << QString();
 +    QTest::newRow("ar_SA") << "ar_SA" << QString();
 +    QTest::newRow("hi_IN") << "hi_IN" << QString();
 +    QTest::newRow("zh_CN") << "zh_CN" << QString();
 +    QTest::newRow("th_TH") << "th_TH" << QString();
 +}
 +
 +void tst_qqmllocale::numberToLocaleCurrencyString()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(QString, symbol);
 +
 +    QQmlComponent c(&engine, testFileUrl("number.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    double number = 2344423.3289;
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QLocale l(locale);
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "toLocaleCurrencyString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(number)),
 +        Q_ARG(QVariant, QVariant(symbol)));
 +
 +    QCOMPARE(val.toString(), l.toCurrencyString(number, symbol));
 +}
 +
 +void tst_qqmllocale::numberFromLocaleString_data()
 +{
 +    QTest::addColumn<QString>("locale");
 +    QTest::addColumn<double>("number");
 +
 +    QTest::newRow("en_US 1") << "en_US" << 1234567.2345;
 +    QTest::newRow("en_US 2") << "en_US" << 0.234;
 +    QTest::newRow("en_US 3") << "en_US" << 234.0;
 +    QTest::newRow("de_DE") << "de_DE" << 1234567.2345;
 +    QTest::newRow("ar_SA") << "ar_SA" << 1234567.2345;
 +    QTest::newRow("hi_IN") << "hi_IN" << 1234567.2345;
 +    QTest::newRow("zh_CN") << "zh_CN" << 1234567.2345;
 +    QTest::newRow("th_TH") << "th_TH" << 1234567.2345;
 +}
 +
 +void tst_qqmllocale::numberFromLocaleString()
 +{
 +    QFETCH(QString, locale);
 +    QFETCH(double, number);
 +
 +    QQmlComponent c(&engine, testFileUrl("number.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QLocale l(locale);
 +    QString strNumber = l.toString(number, 'f');
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant(locale)));
 +
 +    QVariant val;
 +    QMetaObject::invokeMethod(obj, "fromLocaleString", Qt::DirectConnection,
 +        Q_RETURN_ARG(QVariant, val),
 +        Q_ARG(QVariant, QVariant(strNumber)));
 +
 +    QCOMPARE(val.toDouble(), l.toDouble(strNumber));
 +}
 +
 +void tst_qqmllocale::numberConstToLocaleString()
 +{
 +    QQmlComponent c(&engine, testFileUrl("number.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    QMetaObject::invokeMethod(obj, "setLocale", Qt::DirectConnection,
 +        Q_ARG(QVariant, QVariant("en_US")));
 +
 +    QLocale l("en_US");
 +    QCOMPARE(obj->property("const1").toString(), l.toString(1234.56, 'f', 2));
 +    QCOMPARE(obj->property("const2").toString(), l.toString(1234., 'f', 2));
 +}
 +
 +void tst_qqmllocale::stringLocaleCompare_data()
 +{
 +    QTest::addColumn<QString>("string1");
 +    QTest::addColumn<QString>("string2");
 +
 +    QTest::newRow("before") << "a" << "b";
 +    QTest::newRow("equal") << "a" << "a";
 +    QTest::newRow("after") << "b" << "a";
 +
 +    // Copied from QString::localeAwareCompare tests
 +    // We don't actually change locale - we just care that String.localeCompare()
 +    // matches QString::localeAwareCompare();
 +    QTest::newRow("swedish1") << QString("\xe5") << QString("\xe4");
 +    QTest::newRow("swedish2") << QString("\xe4") << QString("\xf6");
 +    QTest::newRow("swedish3") << QString("\xe5") << QString("\xf6");
 +    QTest::newRow("swedish4") << QString("z") << QString("\xe5");
 +
 +    QTest::newRow("german1") << QString("z") << QString("\xe4");
 +    QTest::newRow("german2") << QString("\xe4") << QString("\xf6");
 +    QTest::newRow("german3") << QString("z") << QString("\xf6");
 +}
 +
 +void tst_qqmllocale::stringLocaleCompare()
 +{
 +    QFETCH(QString, string1);
 +    QFETCH(QString, string2);
 +
 +    QQmlComponent c(&engine, testFileUrl("localeCompare.qml"));
 +
 +    QObject *obj = c.create();
 +    QVERIFY(obj);
 +
 +    obj->setProperty("string1", string1);
 +    obj->setProperty("string2", string2);
 +
 +    QCOMPARE(obj->property("comparison").toInt(), QString::localeAwareCompare(string1, string2));
 +}
 +
 +QTEST_MAIN(tst_qqmllocale)
 +
 +#include "tst_qqmllocale.moc"
index 0000000,0000000..b87a7cd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,14 @@@
++CONFIG += testcase
++TARGET = tst_qqmlmetaobject
++macx:CONFIG -= app_bundle
++
++SOURCES += tst_qqmlmetaobject.cpp
++
++include (../../shared/util.pri)
++
++testDataFiles.files = data
++testDataFiles.path = .
++DEPLOYMENT += testDataFiles
++
++CONFIG += parallel_test
++QT += qml testlib
index 0000000,0000000..6cadc35
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,364 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the test suite of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include <QtTest/QtTest>
++#include <QtQml/qqmlcomponent.h>
++#include <QtQml/qqmlengine.h>
++#include "../../shared/util.h"
++
++Q_DECLARE_METATYPE(QMetaMethod::MethodType)
++
++class MyQmlObject : public QObject
++{
++    Q_OBJECT
++};
++QML_DECLARE_TYPE(MyQmlObject)
++
++class tst_QQmlMetaObject : public QQmlDataTest
++{
++    Q_OBJECT
++private slots:
++    void initTestCase();
++
++    void property_data();
++    void property();
++    void method_data();
++    void method();
++
++private:
++    MyQmlObject myQmlObject;
++};
++
++void tst_QQmlMetaObject::initTestCase()
++{
++    QQmlDataTest::initTestCase();
++
++    qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObject");
++}
++
++void tst_QQmlMetaObject::property_data()
++{
++    QTest::addColumn<QString>("testFile");
++    QTest::addColumn<QByteArray>("cppTypeName");
++    QTest::addColumn<int>("cppType");
++    QTest::addColumn<bool>("isDefault");
++    QTest::addColumn<QVariant>("expectedValue");
++    QTest::addColumn<bool>("isWritable");
++    QTest::addColumn<QVariant>("newValue");
++
++    QTest::newRow("int") << "property.int.qml"
++            << QByteArray("int") << int(QMetaType::Int)
++            << false // default
++            << QVariant(19) << true << QVariant(42);
++    QTest::newRow("bool") << "property.bool.qml"
++            << QByteArray("bool") << int(QMetaType::Bool)
++            << true // default
++            << QVariant(true) << true << QVariant(false);
++    QTest::newRow("real") << "property.real.qml"
++            << QByteArray("double") << int(QMetaType::Double)
++            << false // default
++            << QVariant(double(21))
++            << true // writable
++            << QVariant(double(37));
++    QTest::newRow("string") << "property.string.qml"
++            << QByteArray("QString") << int(QMetaType::QString)
++            << true // default
++            << QVariant(QString::fromLatin1("dog"))
++            << true // writable
++            << QVariant(QString::fromLatin1("food"));
++    QTest::newRow("url") << "property.url.qml"
++            << QByteArray("QUrl") << int(QMetaType::QUrl)
++            << false // default
++            << QVariant(QUrl("http://foo.bar"))
++            << true //writable
++            << QVariant(QUrl("http://bar.baz"));
++    QTest::newRow("color") << "property.color.qml"
++            << QByteArray("QColor") << int(QMetaType::QColor)
++            << true // default
++            << QVariant(QColor("#ff0000"))
++            << true // writable
++            << QVariant(QColor("#00ff00"));
++    QTest::newRow("date") << "property.date.qml"
++            << QByteArray("QDateTime") << int(QMetaType::QDateTime)
++            << false // default
++            << QVariant(QDateTime(QDate(2012, 2, 7)))
++            << true // writable
++            << QVariant(QDateTime(QDate(2010, 7, 2)));
++    QTest::newRow("variant") << "property.variant.qml"
++            << QByteArray("QVariant") << int(QMetaType::QVariant)
++            << true // default
++            << QVariant(QPointF(12, 34))
++            << true // writable
++            << QVariant(QSizeF(45, 67));
++    QTest::newRow("var") << "property.var.qml"
++            << QByteArray("QVariant") << int(QMetaType::QVariant)
++            << false // default
++            << QVariant(QVariantList() << 5 << true << "ciao")
++            << true // writable
++            << QVariant(QVariantList() << 17.0);
++    QTest::newRow("QtObject") << "property.QtObject.qml"
++            << QByteArray("QObject*") << int(QMetaType::QObjectStar)
++            << false // default
++            << QVariant()
++            << true // writable
++            << QVariant::fromValue(static_cast<QObject*>(this));
++    QTest::newRow("list<QtObject>") << "property.list.QtObject.qml"
++            << QByteArray("QQmlListProperty<QObject>")
++            << qMetaTypeId<QQmlListProperty<QObject> >()
++            << false // default
++            << QVariant()
++            << false // writable
++            << QVariant();
++    QTest::newRow("MyQmlObject") << "property.MyQmlObject.qml"
++            << QByteArray("MyQmlObject*") << qMetaTypeId<MyQmlObject*>()
++            << false // default
++            << QVariant()
++            << true // writable
++            << QVariant::fromValue(&myQmlObject);
++    QTest::newRow("list<MyQmlObject>") << "property.list.MyQmlObject.qml"
++            << QByteArray("QQmlListProperty<MyQmlObject>")
++            << qMetaTypeId<QQmlListProperty<MyQmlObject> >()
++            << false // default
++            << QVariant()
++            << false // writable
++            << QVariant();
++    QTest::newRow("alias") << "property.alias.qml"
++            << QByteArray("QString") << int(QMetaType::QString)
++            << false // default
++            << QVariant(QString::fromLatin1("Joe"))
++            << true // writable
++            << QVariant(QString::fromLatin1("Bob"));
++    QTest::newRow("alias-2") << "property.alias.2.qml"
++            << QByteArray("QObject*") << int(QMetaType::QObjectStar)
++            << false // default
++            << QVariant()
++            << false // writable
++            << QVariant();
++    QTest::newRow("alias-3") << "property.alias.3.qml"
++            << QByteArray("QString") << int(QMetaType::QString)
++            << false // default
++            << QVariant(QString::fromLatin1("Arial"))
++            << true // writable
++            << QVariant(QString::fromLatin1("Helvetica"));
++}
++
++void tst_QQmlMetaObject::property()
++{
++    QFETCH(QString, testFile);
++    QFETCH(QByteArray, cppTypeName);
++    QFETCH(int, cppType);
++    QFETCH(bool, isDefault);
++    QFETCH(QVariant, expectedValue);
++    QFETCH(bool, isWritable);
++    QFETCH(QVariant, newValue);
++
++    QQmlEngine engine;
++    QQmlComponent component(&engine, testFileUrl(testFile));
++    QObject *object = component.create();
++    QVERIFY(object != 0);
++
++    const QMetaObject *mo = object->metaObject();
++    QVERIFY(mo->superClass() != 0);
++    QVERIFY(QByteArray(mo->className()).contains("_QML_"));
++    QCOMPARE(mo->propertyOffset(), mo->superClass()->propertyCount());
++    QCOMPARE(mo->propertyCount(), mo->superClass()->propertyCount() + 1);
++
++    QMetaProperty prop = mo->property(mo->propertyOffset());
++    QCOMPARE(prop.name(), "test");
++
++    QCOMPARE(QByteArray(prop.typeName()), cppTypeName);
++    QEXPECT_FAIL("QtObject", "prop.type() returns UserType for QtObject properties", Continue);
++    QEXPECT_FAIL("alias-2", "prop.type() returns UserType for QtObject properties", Continue);
++    if (prop.userType() < QMetaType::User)
++        QCOMPARE(prop.type(), QVariant::Type(cppType));
++    QCOMPARE(prop.userType(), cppType);
++
++    QVERIFY(!prop.isConstant());
++    QVERIFY(!prop.isDesignable());
++    QVERIFY(!prop.isEnumType());
++    QVERIFY(!prop.isFinal());
++    QVERIFY(!prop.isFlagType());
++    QVERIFY(prop.isReadable());
++    QVERIFY(!prop.isResettable());
++    QVERIFY(prop.isScriptable());
++    QVERIFY(!prop.isStored());
++    QVERIFY(!prop.isUser());
++    QVERIFY(prop.isValid());
++    QCOMPARE(prop.isWritable(), isWritable);
++
++    QCOMPARE(mo->classInfoOffset(), mo->superClass()->classInfoCount());
++    QCOMPARE(mo->classInfoCount(), mo->superClass()->classInfoCount() + (isDefault ? 1 : 0));
++    if (isDefault) {
++        QMetaClassInfo info = mo->classInfo(mo->classInfoOffset());
++        QCOMPARE(info.name(), "DefaultProperty");
++        QCOMPARE(info.value(), "test");
++    }
++
++    QCOMPARE(mo->methodOffset(), mo->superClass()->methodCount());
++    QCOMPARE(mo->methodCount(), mo->superClass()->methodCount() + 1); // the signal
++
++    QVERIFY(prop.notifySignalIndex() != -1);
++    QMetaMethod signal = prop.notifySignal();
++    QCOMPARE(signal.methodType(), QMetaMethod::Signal);
++    QCOMPARE(signal.signature(), "testChanged()");
++    QCOMPARE(signal.access(), QMetaMethod::Protected);
++    QCOMPARE(signal.parameterTypes(), QList<QByteArray>());
++    QCOMPARE(signal.parameterNames(), QList<QByteArray>());
++    QCOMPARE(signal.tag(), "");
++    QCOMPARE(signal.typeName(), "");
++
++    QSignalSpy changedSpy(object, SIGNAL(testChanged()));
++    QObject::connect(object, SIGNAL(testChanged()), object, SLOT(deleteLater()));
++
++    if (expectedValue.isValid())
++        QCOMPARE(prop.read(object), expectedValue);
++    else
++        QVERIFY(prop.read(object).isValid());
++    QCOMPARE(changedSpy.count(), 0);
++
++    if (isWritable) {
++        QVERIFY(prop.write(object, newValue));
++        QCOMPARE(changedSpy.count(), 1);
++        QCOMPARE(prop.read(object), newValue);
++    } else {
++        QVERIFY(!prop.write(object, prop.read(object)));
++        QCOMPARE(changedSpy.count(), 0);
++    }
++
++    delete object;
++}
++
++void tst_QQmlMetaObject::method_data()
++{
++    QTest::addColumn<QString>("testFile");
++    QTest::addColumn<QString>("signature");
++    QTest::addColumn<QMetaMethod::MethodType>("methodType");
++    QTest::addColumn<QString>("returnTypeName");
++    QTest::addColumn<QList<QByteArray> >("parameterTypeNames");
++    QTest::addColumn<QList<QByteArray> >("parameterNames");
++
++    QTest::newRow("testFunction()") << "method.1.qml"
++            << "testFunction()"
++            << QMetaMethod::Slot
++            << "QVariant"
++            << QList<QByteArray>()
++            << QList<QByteArray>();
++    QTest::newRow("testFunction(foo)") << "method.2.qml"
++            << "testFunction(QVariant)"
++            << QMetaMethod::Slot
++            << "QVariant"
++            << (QList<QByteArray>() << "QVariant")
++            << (QList<QByteArray>() << "foo");
++    QTest::newRow("testFunction(foo, bar, baz)") << "method.3.qml"
++            << "testFunction(QVariant,QVariant,QVariant)"
++            << QMetaMethod::Slot
++            << "QVariant"
++            << (QList<QByteArray>() << "QVariant" << "QVariant" << "QVariant")
++            << (QList<QByteArray>() << "foo" << "bar" << "baz");
++    QTest::newRow("testSignal") << "signal.1.qml"
++            << "testSignal()"
++            << QMetaMethod::Signal
++            << ""
++            << QList<QByteArray>()
++            << QList<QByteArray>();
++    QTest::newRow("testSignal(string foo)") << "signal.2.qml"
++            << "testSignal(QString)"
++            << QMetaMethod::Signal
++            << ""
++            << (QList<QByteArray>() << "QString")
++            << (QList<QByteArray>() << "foo");
++    QTest::newRow("testSignal(int foo, bool bar, real baz)") << "signal.3.qml"
++            << "testSignal(int,bool,qreal)"
++            << QMetaMethod::Signal
++            << ""
++            << (QList<QByteArray>() << "int" << "bool" << "qreal")
++            << (QList<QByteArray>() << "foo" << "bar" << "baz");
++    QTest::newRow("testSignal(variant foo, var bar)") << "signal.4.qml"
++            << "testSignal(QVariant,QVariant)"
++            << QMetaMethod::Signal
++            << ""
++            << (QList<QByteArray>() << "QVariant" << "QVariant")
++            << (QList<QByteArray>() << "foo" << "bar");
++    QTest::newRow("testSignal(color foo, date bar, url baz)") << "signal.5.qml"
++            << "testSignal(QColor,QDateTime,QUrl)"
++            << QMetaMethod::Signal
++            << ""
++            << (QList<QByteArray>() << "QColor" << "QDateTime" << "QUrl")
++            << (QList<QByteArray>() << "foo" << "bar" << "baz");
++}
++
++void tst_QQmlMetaObject::method()
++{
++    QFETCH(QString, testFile);
++    QFETCH(QString, signature);
++    QFETCH(QMetaMethod::MethodType, methodType);
++    QFETCH(QString, returnTypeName);
++    QFETCH(QList<QByteArray>, parameterTypeNames);
++    QFETCH(QList<QByteArray>, parameterNames);
++
++    QCOMPARE(parameterTypeNames.size(), parameterNames.size());
++
++    QQmlEngine engine;
++    QQmlComponent component(&engine, testFileUrl(testFile));
++    QObject *object = component.create();
++    QVERIFY(object != 0);
++
++    const QMetaObject *mo = object->metaObject();
++    QVERIFY(mo->superClass() != 0);
++    QVERIFY(QByteArray(mo->className()).contains("_QML_"));
++    QCOMPARE(mo->methodOffset(), mo->superClass()->methodCount());
++    QCOMPARE(mo->methodCount(), mo->superClass()->methodCount() + 1);
++
++    QMetaMethod method = mo->method(mo->methodOffset());
++    QCOMPARE(method.methodType(), methodType);
++    QCOMPARE(QString::fromUtf8(method.signature()), signature);
++    QCOMPARE(method.access(), QMetaMethod::Protected);
++    QCOMPARE(method.parameterTypes(), parameterTypeNames);
++    QCOMPARE(method.parameterNames(), parameterNames);
++    QCOMPARE(method.tag(), "");
++    QCOMPARE(QString::fromUtf8(method.typeName()), returnTypeName);
++
++    delete object;
++}
++
++QTEST_MAIN(tst_QQmlMetaObject)
++
++#include "tst_qqmlmetaobject.moc"
index 53696b3,0000000..03065b2
mode 100644,000000..100644
--- /dev/null
@@@ -1,84 -1,0 +1,84 @@@
- Q_EXPORT_PLUGIN2(plugin, MyPlugin);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <QStringList>
 +#include <QtQml/qqmlextensionplugin.h>
 +#include <QtQml/qqml.h>
 +#include <QDebug>
 +
 +class MyPluginType : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value WRITE setValue)
 +    Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue)
 +
 +public:
 +    MyPluginType(QObject *parent=0) : QObject(parent)
 +    {
 +        qWarning("import2.1 worked");
 +    }
 +
 +    int value() const { return v; }
 +    void setValue(int i) { v = i; }
 +
 +private:
 +    int v;
 +};
 +
 +
 +class MyPlugin : public QQmlExtensionPlugin
 +{
 +    Q_OBJECT
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "../empty.json")
++
 +public:
 +    MyPlugin()
 +    {
 +        qWarning("plugin2.1 created");
 +    }
 +
 +    void registerTypes(const char *uri)
 +    {
 +        Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlPluginType");
 +        qmlRegisterType<MyPluginType>(uri, 2, 1, "MyPluginType");
 +    }
 +};
 +
 +#include "plugin.moc"
index f62b8ad,0000000..e2ff43d
mode 100644,000000..100644
--- /dev/null
@@@ -1,84 -1,0 +1,84 @@@
- Q_EXPORT_PLUGIN2(plugin, MyPlugin);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <QStringList>
 +#include <QtQml/qqmlextensionplugin.h>
 +#include <QtQml/qqml.h>
 +#include <QDebug>
 +
 +class MyPluginType : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value WRITE setValue)
 +    Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue)
 +
 +public:
 +    MyPluginType(QObject *parent=0) : QObject(parent)
 +    {
 +        qWarning("import2 worked");
 +    }
 +
 +    int value() const { return v; }
 +    void setValue(int i) { v = i; }
 +
 +private:
 +    int v;
 +};
 +
 +
 +class MyPlugin : public QQmlExtensionPlugin
 +{
 +    Q_OBJECT
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "../empty.json")
++
 +public:
 +    MyPlugin()
 +    {
 +        qWarning("plugin2 created");
 +    }
 +
 +    void registerTypes(const char *uri)
 +    {
 +        Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlPluginType");
 +        qmlRegisterType<MyPluginType>(uri, 2, 0, "MyPluginType");
 +    }
 +};
 +
 +#include "plugin.moc"
index 470aa7a,0000000..5a91852
mode 100644,000000..100644
--- /dev/null
@@@ -1,83 -1,0 +1,83 @@@
- Q_EXPORT_PLUGIN2(plugin, MyPlugin);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <QStringList>
 +#include <QtQml/qqmlextensionplugin.h>
 +#include <QtQml/qqml.h>
 +#include <QDebug>
 +
 +class MyPluginType : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value WRITE setValue)
 +
 +public:
 +    MyPluginType(QObject *parent=0) : QObject(parent)
 +    {
 +        qWarning("import worked");
 +    }
 +
 +    int value() const { return v; }
 +    void setValue(int i) { v = i; }
 +
 +private:
 +    int v;
 +};
 +
 +
 +class MyPlugin : public QQmlExtensionPlugin
 +{
 +    Q_OBJECT
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "../empty.json")
++
 +public:
 +    MyPlugin()
 +    {
 +        qWarning("plugin created");
 +    }
 +
 +    void registerTypes(const char *uri)
 +    {
 +        Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlPluginType");
 +        qmlRegisterType<MyPluginType>(uri, 1, 0, "MyPluginType");
 +    }
 +};
 +
 +#include "plugin.moc"
index eec8e3f,0000000..66c59fd
mode 100644,000000..100644
--- /dev/null
@@@ -1,73 -1,0 +1,73 @@@
- Q_EXPORT_PLUGIN2(plugin, MyMixedPlugin);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <QStringList>
 +#include <QtQml/qqmlextensionplugin.h>
 +#include <QtQml/qqml.h>
 +#include <QDebug>
 +
 +class BarPluginType : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value)
 +
 +public:
 +    int value() const { return 16; }
 +};
 +
 +
 +class MyMixedPlugin : public QQmlExtensionPlugin
 +{
 +    Q_OBJECT
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "../empty.json")
++
 +public:
 +    MyMixedPlugin()
 +    {
 +    }
 +
 +    void registerTypes(const char *uri)
 +    {
 +        Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlMixedPluginType");
 +        qmlRegisterType<BarPluginType>(uri, 1, 0, "Bar");
 +    }
 +};
 +
 +#include "plugin.moc"
index 8645028,0000000..a3142ef
mode 100644,000000..100644
--- /dev/null
@@@ -1,73 -1,0 +1,73 @@@
- Q_EXPORT_PLUGIN2(plugin, MyMixedPlugin);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <QStringList>
 +#include <QtQml/qqmlextensionplugin.h>
 +#include <QtQml/qqml.h>
 +#include <QDebug>
 +
 +class FloorPluginType : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value);
 +
 +public:
 +    int value() const { return 16; }
 +};
 +
 +
 +class MyMixedPlugin : public QQmlExtensionPlugin
 +{
 +    Q_OBJECT
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "../empty.json")
++
 +public:
 +    MyMixedPlugin()
 +    {
 +    }
 +
 +    void registerTypes(const char *uri)
 +    {
 +        Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlVersionPluginType");
 +        qmlRegisterType<FloorPluginType>(uri, 1, 4, "Floor");
 +    }
 +};
 +
 +#include "plugin.moc"
index 1217df4,0000000..a2262f1
mode 100644,000000..100644
--- /dev/null
@@@ -1,58 -1,0 +1,58 @@@
- Q_EXPORT_PLUGIN2(plugin, MyPlugin);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <QStringList>
 +#include <QtQml/qqmlextensionplugin.h>
 +#include <QtQml/qqml.h>
 +#include <QDebug>
 +
 +class MyPlugin : public QQmlExtensionPlugin
 +{
 +    Q_OBJECT
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "../empty.json")
++
 +public:
 +    void registerTypes(const char *uri)
 +    {
 +        Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestPluginWithQmlFile");
 +    }
 +};
 +
 +#include "plugin.moc"
index e0257fe,0000000..a5fc6c1
mode 100644,000000..100644
--- /dev/null
@@@ -1,83 -1,0 +1,83 @@@
- Q_EXPORT_PLUGIN2(plugin, MyPlugin);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <QStringList>
 +#include <QtQml/qqmlextensionplugin.h>
 +#include <QtQml/qqml.h>
 +#include <QDebug>
 +
 +class MyPluginType : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int value READ value WRITE setValue)
 +
 +public:
 +    MyPluginType(QObject *parent=0) : QObject(parent)
 +    {
 +        qWarning("import worked");
 +    }
 +
 +    int value() const { return v; }
 +    void setValue(int i) { v = i; }
 +
 +private:
 +    int v;
 +};
 +
 +
 +class MyPlugin : public QQmlExtensionPlugin
 +{
 +    Q_OBJECT
++    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "../empty.json")
++
 +public:
 +    MyPlugin()
 +    {
 +        qWarning("plugin created");
 +    }
 +
 +    void registerTypes(const char *uri)
 +    {
 +        Q_ASSERT(QLatin1String(uri) == "com.nokia.WrongCase");
 +        qmlRegisterType<MyPluginType>(uri, 1, 0, "MyPluginType");
 +    }
 +};
 +
 +#include "plugin.moc"
index 695dbe4,0000000..0aa223e
mode 100644,000000..100644
--- /dev/null
@@@ -1,1306 -1,0 +1,1319 @@@
-     /*
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include <qtest.h>
 +#include <QQmlEngine>
 +#include <QQmlComponent>
 +#include <QDebug>
 +#include <private/qqmlvaluetype_p.h>
 +#include "../../shared/util.h"
 +#include "testtypes.h"
 +
 +QT_BEGIN_NAMESPACE
 +extern int qt_defaultDpi();
 +QT_END_NAMESPACE
 +
 +class tst_qqmlvaluetypes : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_qqmlvaluetypes() {}
 +
 +private slots:
 +    void initTestCase();
 +
 +    void point();
 +    void pointf();
 +    void size();
 +    void sizef();
 +    void sizereadonly();
 +    void rect();
 +    void rectf();
 +    void vector2d();
 +    void vector3d();
 +    void vector4d();
 +    void quaternion();
 +    void matrix4x4();
 +    void font();
 +    void color();
 +    void variant();
 +
 +    void bindingAssignment();
 +    void bindingRead();
 +    void staticAssignment();
 +    void scriptAccess();
 +    void autoBindingRemoval();
 +    void valueSources();
 +    void valueInterceptors();
 +    void bindingConflict();
 +    void deletedObject();
 +    void bindingVariantCopy();
 +    void scriptVariantCopy();
 +    void cppClasses();
 +    void enums();
 +    void conflictingBindings();
 +    void returnValues();
 +    void varAssignment();
 +    void bindingsSpliceCorrectly();
++    void nonValueTypeComparison();
 +
 +private:
 +    QQmlEngine engine;
 +};
 +
 +void tst_qqmlvaluetypes::initTestCase()
 +{
 +    QQmlDataTest::initTestCase();
 +    registerTypes();
 +}
 +
 +void tst_qqmlvaluetypes::point()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("point_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("p_x").toInt(), 10);
 +        QCOMPARE(object->property("p_y").toInt(), 4);
 +        QCOMPARE(object->property("copy"), QVariant(QPoint(10, 4)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("point_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->point(), QPoint(11, 12));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("point_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QPoint(10, 4)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), true);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +        QCOMPARE(object->property("equalsOther").toBool(), false);
 +        QCOMPARE(object->property("pointEqualsPointf").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::pointf()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("pointf_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(float(object->property("p_x").toDouble()), float(11.3));
 +        QCOMPARE(float(object->property("p_y").toDouble()), float(-10.9));
 +        QCOMPARE(object->property("copy"), QVariant(QPointF(11.3, -10.9)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("pointf_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->pointf(), QPointF(6.8, 9.3));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("pointf_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QPointF(11.3, -10.9)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), true);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +        QCOMPARE(object->property("equalsOther").toBool(), false);
 +        QCOMPARE(object->property("pointfEqualsPoint").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::size()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("size_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("s_width").toInt(), 1912);
 +        QCOMPARE(object->property("s_height").toInt(), 1913);
 +        QCOMPARE(object->property("copy"), QVariant(QSize(1912, 1913)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("size_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->size(), QSize(13, 88));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("size_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QSize(1912, 1913)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), true);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +        QCOMPARE(object->property("equalsOther").toBool(), false);
 +        QCOMPARE(object->property("sizeEqualsSizef").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::sizef()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("sizef_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(float(object->property("s_width").toDouble()), float(0.1));
 +        QCOMPARE(float(object->property("s_height").toDouble()), float(100923.2));
 +        QCOMPARE(object->property("copy"), QVariant(QSizeF(0.1, 100923.2)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("sizef_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->sizef(), QSizeF(44.3, 92.8));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("sizef_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QSizeF(0.1, 100923)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), true);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +        QCOMPARE(object->property("equalsOther").toBool(), false);
 +        QCOMPARE(object->property("sizefEqualsSize").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::variant()
 +{
 +    QQmlComponent component(&engine, testFileUrl("variant_read.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(float(object->property("s_width").toDouble()), float(0.1));
 +    QCOMPARE(float(object->property("s_height").toDouble()), float(100923.2));
 +    QCOMPARE(object->property("copy"), QVariant(QSizeF(0.1, 100923.2)));
 +
 +    delete object;
 +}
 +
 +void tst_qqmlvaluetypes::sizereadonly()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("sizereadonly_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("s_width").toInt(), 1912);
 +        QCOMPARE(object->property("s_height").toInt(), 1913);
 +        QCOMPARE(object->property("copy"), QVariant(QSize(1912, 1913)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("sizereadonly_writeerror.qml"));
 +        QVERIFY(component.isError());
 +        QCOMPARE(component.errors().at(0).description(), QLatin1String("Invalid property assignment: \"sizereadonly\" is a read-only property"));
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("sizereadonly_writeerror2.qml"));
 +        QVERIFY(component.isError());
 +        QCOMPARE(component.errors().at(0).description(), QLatin1String("Invalid property assignment: \"sizereadonly\" is a read-only property"));
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("sizereadonly_writeerror3.qml"));
 +        QVERIFY(component.isError());
 +        QCOMPARE(component.errors().at(0).description(), QLatin1String("Invalid property assignment: \"sizereadonly\" is a read-only property"));
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("sizereadonly_writeerror4.qml"));
 +
 +        QObject *object = component.create();
 +        QVERIFY(object);
 +
 +        QCOMPARE(object->property("sizereadonly").toSize(), QSize(1912, 1913));
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::rect()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("rect_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("r_x").toInt(), 2);
 +        QCOMPARE(object->property("r_y").toInt(), 3);
 +        QCOMPARE(object->property("r_width").toInt(), 109);
 +        QCOMPARE(object->property("r_height").toInt(), 102);
 +        QCOMPARE(object->property("copy"), QVariant(QRect(2, 3, 109, 102)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("rect_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->rect(), QRect(1234, 7, 56, 63));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("rect_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QRect(2, 3, 109, 102)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), true);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +        QCOMPARE(object->property("equalsOther").toBool(), false);
 +        QCOMPARE(object->property("rectEqualsRectf").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::rectf()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("rectf_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(float(object->property("r_x").toDouble()), float(103.8));
 +        QCOMPARE(float(object->property("r_y").toDouble()), float(99.2));
 +        QCOMPARE(float(object->property("r_width").toDouble()), float(88.1));
 +        QCOMPARE(float(object->property("r_height").toDouble()), float(77.6));
 +        QCOMPARE(object->property("copy"), QVariant(QRectF(103.8, 99.2, 88.1, 77.6)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("rectf_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->rectf(), QRectF(70.1, -113.2, 80924.8, 99.2));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("rectf_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QRectF(103.8, 99.2, 88.1, 77.6)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), true);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +        QCOMPARE(object->property("equalsOther").toBool(), false);
 +        QCOMPARE(object->property("rectfEqualsRect").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::vector2d()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("vector2d_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE((float)object->property("v_x").toDouble(), (float)32.88);
 +        QCOMPARE((float)object->property("v_y").toDouble(), (float)1.3);
 +        QCOMPARE(object->property("copy"), QVariant(QVector2D(32.88, 1.3)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("vector2d_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->vector2(), QVector2D(-0.3, -12.9));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("vector2d_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QVector2D(32.88, 1.3)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::vector3d()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("vector3d_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE((float)object->property("v_x").toDouble(), (float)23.88);
 +        QCOMPARE((float)object->property("v_y").toDouble(), (float)3.1);
 +        QCOMPARE((float)object->property("v_z").toDouble(), (float)4.3);
 +        QCOMPARE(object->property("copy"), QVariant(QVector3D(23.88, 3.1, 4.3)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("vector3d_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->vector(), QVector3D(-0.3, -12.9, 907.4));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("vector3d_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QVector3D(23.88, 3.1, 4.3)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), true);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +        QCOMPARE(object->property("equalsOther").toBool(), false);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::vector4d()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("vector4d_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE((float)object->property("v_x").toDouble(), (float)54.2);
 +        QCOMPARE((float)object->property("v_y").toDouble(), (float)23.88);
 +        QCOMPARE((float)object->property("v_z").toDouble(), (float)3.1);
 +        QCOMPARE((float)object->property("v_w").toDouble(), (float)4.3);
 +        QCOMPARE(object->property("copy"), QVariant(QVector4D(54.2, 23.88, 3.1, 4.3)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("vector4d_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->vector4(), QVector4D(-0.3, -12.9, 907.4, 88.5));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("vector4d_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QVector4D(54.2, 23.88, 3.1, 4.3)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::quaternion()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("quaternion_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE((float)object->property("v_scalar").toDouble(), (float)4.3);
 +        QCOMPARE((float)object->property("v_x").toDouble(), (float)54.2);
 +        QCOMPARE((float)object->property("v_y").toDouble(), (float)23.88);
 +        QCOMPARE((float)object->property("v_z").toDouble(), (float)3.1);
 +        QCOMPARE(object->property("copy"), QVariant(QQuaternion(4.3, 54.2, 23.88, 3.1)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("quaternion_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->quaternion(), QQuaternion(88.5, -0.3, -12.9, 907.4));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("quaternion_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QQuaternion(4.3, 54.2, 23.88, 3.1)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::matrix4x4()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("matrix4x4_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE((float)object->property("v_m11").toDouble(), (float)1);
 +        QCOMPARE((float)object->property("v_m12").toDouble(), (float)2);
 +        QCOMPARE((float)object->property("v_m13").toDouble(), (float)3);
 +        QCOMPARE((float)object->property("v_m14").toDouble(), (float)4);
 +        QCOMPARE((float)object->property("v_m21").toDouble(), (float)5);
 +        QCOMPARE((float)object->property("v_m22").toDouble(), (float)6);
 +        QCOMPARE((float)object->property("v_m23").toDouble(), (float)7);
 +        QCOMPARE((float)object->property("v_m24").toDouble(), (float)8);
 +        QCOMPARE((float)object->property("v_m31").toDouble(), (float)9);
 +        QCOMPARE((float)object->property("v_m32").toDouble(), (float)10);
 +        QCOMPARE((float)object->property("v_m33").toDouble(), (float)11);
 +        QCOMPARE((float)object->property("v_m34").toDouble(), (float)12);
 +        QCOMPARE((float)object->property("v_m41").toDouble(), (float)13);
 +        QCOMPARE((float)object->property("v_m42").toDouble(), (float)14);
 +        QCOMPARE((float)object->property("v_m43").toDouble(), (float)15);
 +        QCOMPARE((float)object->property("v_m44").toDouble(), (float)16);
 +        QCOMPARE(object->property("copy"),
 +                 QVariant(QMatrix4x4(1, 2, 3, 4,
 +                                     5, 6, 7, 8,
 +                                     9, 10, 11, 12,
 +                                     13, 14, 15, 16)));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("matrix4x4_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->matrix(), QMatrix4x4(11, 12, 13, 14,
 +                                              21, 22, 23, 24,
 +                                              31, 32, 33, 34,
 +                                              41, 42, 43, 44));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("matrix4x4_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QMatrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)");
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::font()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("font_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->property("f_family").toString(), object->font().family());
 +        QCOMPARE(object->property("f_bold").toBool(), object->font().bold());
 +        QCOMPARE(object->property("f_weight").toInt(), object->font().weight());
 +        QCOMPARE(object->property("f_italic").toBool(), object->font().italic());
 +        QCOMPARE(object->property("f_underline").toBool(), object->font().underline());
 +        QCOMPARE(object->property("f_overline").toBool(), object->font().overline());
 +        QCOMPARE(object->property("f_strikeout").toBool(), object->font().strikeOut());
 +        QCOMPARE(object->property("f_pointSize").toDouble(), object->font().pointSizeF());
 +        QCOMPARE(object->property("f_pixelSize").toInt(), int((object->font().pointSizeF() * qt_defaultDpi()) / qreal(72.)));
 +        QCOMPARE(object->property("f_capitalization").toInt(), (int)object->font().capitalization());
 +        QCOMPARE(object->property("f_letterSpacing").toDouble(), object->font().letterSpacing());
 +        QCOMPARE(object->property("f_wordSpacing").toDouble(), object->font().wordSpacing());
 +
 +        QCOMPARE(object->property("copy"), QVariant(object->font()));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("font_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QFont font;
 +        font.setFamily("Helvetica");
 +        font.setBold(false);
 +        font.setWeight(QFont::Normal);
 +        font.setItalic(false);
 +        font.setUnderline(false);
 +        font.setStrikeOut(false);
 +        font.setPointSize(15);
 +        font.setCapitalization(QFont::AllLowercase);
 +        font.setLetterSpacing(QFont::AbsoluteSpacing, 9.7);
 +        font.setWordSpacing(11.2);
 +
 +        QFont f = object->font();
 +        QCOMPARE(f.family(), font.family());
 +        QCOMPARE(f.bold(), font.bold());
 +        QCOMPARE(f.weight(), font.weight());
 +        QCOMPARE(f.italic(), font.italic());
 +        QCOMPARE(f.underline(), font.underline());
 +        QCOMPARE(f.strikeOut(), font.strikeOut());
 +        QCOMPARE(f.pointSize(), font.pointSize());
 +        QCOMPARE(f.capitalization(), font.capitalization());
 +        QCOMPARE(f.letterSpacing(), font.letterSpacing());
 +        QCOMPARE(f.wordSpacing(), font.wordSpacing());
 +
 +        delete object;
 +    }
 +
 +    // Test pixelSize
 +    {
 +        QQmlComponent component(&engine, testFileUrl("font_write.2.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->font().pixelSize(), 10);
 +
 +        delete object;
 +    }
 +
 +    // Test pixelSize and pointSize
 +    {
 +        QQmlComponent component(&engine, testFileUrl("font_write.3.qml"));
 +        QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size. ");
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->font().pixelSize(), 10);
 +
 +        delete object;
 +    }
 +    {
 +        QQmlComponent component(&engine, testFileUrl("font_write.4.qml"));
 +        QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size. ");
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->font().pixelSize(), 10);
 +
 +        delete object;
 +    }
 +    {
 +        QQmlComponent component(&engine, testFileUrl("font_write.5.qml"));
 +        QObject *object = qobject_cast<QObject *>(component.create());
 +        QVERIFY(object != 0);
 +        MyTypeObject *object1 = object->findChild<MyTypeObject *>("object1");
 +        QVERIFY(object1 != 0);
 +        MyTypeObject *object2 = object->findChild<MyTypeObject *>("object2");
 +        QVERIFY(object2 != 0);
 +
 +        QCOMPARE(object1->font().pixelSize(), 19);
 +        QCOMPARE(object2->font().pointSize(), 14);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("font_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QString tostring = QLatin1String("QFont(") + object->font().toString() + QLatin1Char(')');
 +        QCOMPARE(object->property("tostring").toString(), tostring);
 +        QCOMPARE(object->property("equalsString").toBool(), true);
 +        QCOMPARE(object->property("equalsColor").toBool(), false);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +        QCOMPARE(object->property("equalsSelf").toBool(), true);
 +
 +        delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::color()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("color_read.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE((float)object->property("v_r").toDouble(), (float)0.2);
 +        QCOMPARE((float)object->property("v_g").toDouble(), (float)0.88);
 +        QCOMPARE((float)object->property("v_b").toDouble(), (float)0.6);
 +        QCOMPARE((float)object->property("v_a").toDouble(), (float)0.34);
 +        QColor comparison;
 +        comparison.setRedF(0.2);
 +        comparison.setGreenF(0.88);
 +        comparison.setBlueF(0.6);
 +        comparison.setAlphaF(0.34);
 +        QCOMPARE(object->property("copy"), QVariant(comparison));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("color_write.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QColor newColor;
 +        newColor.setRedF(0.5);
 +        newColor.setGreenF(0.38);
 +        newColor.setBlueF(0.3);
 +        newColor.setAlphaF(0.7);
 +        QCOMPARE(object->color(), newColor);
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("color_compare.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +        QString colorString("#33e199");
 +        QCOMPARE(object->property("colorToString").toString(), colorString);
 +        QCOMPARE(object->property("colorEqualsIdenticalRgba").toBool(), true);
 +        QCOMPARE(object->property("colorEqualsDifferentAlpha").toBool(), false);
 +        QCOMPARE(object->property("colorEqualsDifferentRgba").toBool(), false);
 +        QCOMPARE(object->property("colorToStringEqualsColorString").toBool(), true);
 +        QCOMPARE(object->property("colorToStringEqualsDifferentAlphaString").toBool(), true);
 +        QCOMPARE(object->property("colorToStringEqualsDifferentRgbaString").toBool(), false);
 +        QCOMPARE(object->property("colorEqualsColorString").toBool(), true);          // maintaining behaviour with QtQuick 1.0
 +        QCOMPARE(object->property("colorEqualsDifferentAlphaString").toBool(), true); // maintaining behaviour with QtQuick 1.0
 +        QCOMPARE(object->property("colorEqualsDifferentRgbaString").toBool(), false);
 +
 +        QCOMPARE(object->property("equalsColor").toBool(), true);
 +        QCOMPARE(object->property("equalsVector3d").toBool(), false);
 +        QCOMPARE(object->property("equalsSize").toBool(), false);
 +        QCOMPARE(object->property("equalsPoint").toBool(), false);
 +        QCOMPARE(object->property("equalsRect").toBool(), false);
 +
 +        // Color == Property and Property == Color should return the same result.
 +        QCOMPARE(object->property("equalsColorRHS").toBool(), object->property("equalsColor").toBool());
 +        QCOMPARE(object->property("colorEqualsCopy").toBool(), true);
 +        QCOMPARE(object->property("copyEqualsColor").toBool(), object->property("colorEqualsCopy").toBool());
 +
 +        delete object;
 +    }
 +}
 +
 +// Test bindings can write to value types
 +void tst_qqmlvaluetypes::bindingAssignment()
 +{
 +    QQmlComponent component(&engine, testFileUrl("bindingAssignment.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->rect().x(), 10);
 +
 +    object->setProperty("value", QVariant(92));
 +
 +    QCOMPARE(object->rect().x(), 92);
 +
 +    delete object;
 +}
 +
 +// Test bindings can read from value types
 +void tst_qqmlvaluetypes::bindingRead()
 +{
 +    QQmlComponent component(&engine, testFileUrl("bindingRead.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("value").toInt(), 2);
 +
 +    object->setRect(QRect(19, 3, 88, 2));
 +
 +    QCOMPARE(object->property("value").toInt(), 19);
 +
 +    delete object;
 +}
 +
 +// Test static values can assign to value types
 +void tst_qqmlvaluetypes::staticAssignment()
 +{
 +    QQmlComponent component(&engine, testFileUrl("staticAssignment.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->rect().x(), 9);
 +
 +    delete object;
 +}
 +
 +// Test scripts can read/write value types
 +void tst_qqmlvaluetypes::scriptAccess()
 +{
 +    QQmlComponent component(&engine, testFileUrl("scriptAccess.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("valuePre").toInt(), 2);
 +    QCOMPARE(object->rect().x(), 19);
 +    QCOMPARE(object->property("valuePost").toInt(), 19);
 +
 +    delete object;
 +}
 +
 +// Test that assigning a constant from script removes any binding
 +void tst_qqmlvaluetypes::autoBindingRemoval()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("autoBindingRemoval.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->rect().x(), 10);
 +
 +        object->setProperty("value", QVariant(13));
 +
 +        QCOMPARE(object->rect().x(), 13);
 +
 +        object->emitRunScript();
 +
 +        QCOMPARE(object->rect().x(), 42);
 +
 +        object->setProperty("value", QVariant(92));
 +
 +        QCOMPARE(object->rect().x(), 42);
 +
 +        delete object;
 +    }
 +
- */
 +    {
 +        QQmlComponent component(&engine, testFileUrl("autoBindingRemoval.2.qml"));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        QCOMPARE(object->rect().x(), 10);
 +
 +        object->setProperty("value", QVariant(13));
 +
 +        QCOMPARE(object->rect().x(), 13);
 +
 +        object->emitRunScript();
 +
 +        QCOMPARE(object->rect(), QRect(10, 10, 10, 10));
 +
 +        object->setProperty("value", QVariant(92));
 +
 +        QCOMPARE(object->rect(), QRect(10, 10, 10, 10));
 +
 +        delete object;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("autoBindingRemoval.3.qml"));
++        QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QRect";
++        QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +        MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +        QVERIFY(object != 0);
 +
 +        object->setProperty("value", QVariant(QRect(9, 22, 33, 44)));
 +
 +        QCOMPARE(object->rect(), QRect(9, 22, 33, 44));
 +
 +        object->emitRunScript();
 +
 +        QCOMPARE(object->rect(), QRect(44, 22, 33, 44));
 +
 +        object->setProperty("value", QVariant(QRect(19, 3, 4, 8)));
 +
 +        QCOMPARE(object->rect(), QRect(44, 22, 33, 44));
 +
 +        delete object;
 +    }
 +}
 +
 +// Test that property value sources assign to value types
 +void tst_qqmlvaluetypes::valueSources()
 +{
 +    QQmlComponent component(&engine, testFileUrl("valueSources.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->rect().x(), 3345);
 +
 +    delete object;
 +}
 +
 +static void checkNoErrors(QQmlComponent& component)
 +{
 +    QList<QQmlError> errors = component.errors();
 +    if (errors.isEmpty())
 +        return;
 +    for (int ii = 0; ii < errors.count(); ++ii) {
 +        const QQmlError &error = errors.at(ii);
 +        qWarning("%d:%d:%s",error.line(),error.column(),error.description().toUtf8().constData());
 +    }
 +}
 +
 +// Test that property value interceptors can be applied to value types
 +void tst_qqmlvaluetypes::valueInterceptors()
 +{
 +    QQmlComponent component(&engine, testFileUrl("valueInterceptors.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    checkNoErrors(component);
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->rect().x(), 13);
 +
 +    object->setProperty("value", 99);
 +
 +    QCOMPARE(object->rect().x(), 112);
 +
 +    delete object;
 +}
 +
 +// Test that you can't assign a binding to the "root" value type, and a sub-property
 +void tst_qqmlvaluetypes::bindingConflict()
 +{
 +    QQmlComponent component(&engine, testFileUrl("bindingConflict.qml"));
 +    QCOMPARE(component.isError(), true);
 +}
 +
 +#define CPP_TEST(type, v) \
 +{ \
 +    type *t = new type; \
 +    QVariant value(v); \
 +    t->setValue(value); \
 +    QCOMPARE(t->value(), value); \
 +    delete t; \
 +}
 +
 +// Test that accessing a reference to a valuetype after the owning object is deleted
 +// doesn't crash
 +void tst_qqmlvaluetypes::deletedObject()
 +{
 +    QQmlComponent component(&engine, testFileUrl("deletedObject.qml"));
 +    QTest::ignoreMessage(QtDebugMsg, "Test: 2");
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QObject *dObject = qvariant_cast<QObject *>(object->property("object"));
 +    QVERIFY(dObject != 0);
 +    delete dObject;
 +
 +    QTest::ignoreMessage(QtDebugMsg, "Test: undefined");
 +    object->emitRunScript();
 +
 +    delete object;
 +}
 +
 +// Test that value types can be assigned to another value type property in a binding
 +void tst_qqmlvaluetypes::bindingVariantCopy()
 +{
 +    QQmlComponent component(&engine, testFileUrl("bindingVariantCopy.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->rect(), QRect(19, 33, 5, 99));
 +
 +    delete object;
 +}
 +
 +// Test that value types can be assigned to another value type property in script
 +void tst_qqmlvaluetypes::scriptVariantCopy()
 +{
 +    QQmlComponent component(&engine, testFileUrl("scriptVariantCopy.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->rect(), QRect(2, 3, 109, 102));
 +
 +    object->emitRunScript();
 +
 +    QCOMPARE(object->rect(), QRect(19, 33, 5, 99));
 +
 +    delete object;
 +}
 +
 +
 +// Test that the value type classes can be used manually
 +void tst_qqmlvaluetypes::cppClasses()
 +{
 +    CPP_TEST(QQmlPointValueType, QPoint(19, 33));
 +    CPP_TEST(QQmlPointFValueType, QPointF(33.6, -23));
 +    CPP_TEST(QQmlSizeValueType, QSize(-100, 18));
 +    CPP_TEST(QQmlSizeFValueType, QSizeF(-100.7, 18.2));
 +    CPP_TEST(QQmlRectValueType, QRect(13, 39, 10928, 88));
 +    CPP_TEST(QQmlRectFValueType, QRectF(88.2, -90.1, 103.2, 118));
 +    CPP_TEST(QQmlVector2DValueType, QVector2D(19.7, 1002));
 +    CPP_TEST(QQmlVector3DValueType, QVector3D(18.2, 19.7, 1002));
 +    CPP_TEST(QQmlVector4DValueType, QVector4D(18.2, 19.7, 1002, 54));
 +    CPP_TEST(QQmlQuaternionValueType, QQuaternion(18.2, 19.7, 1002, 54));
 +    CPP_TEST(QQmlMatrix4x4ValueType,
 +             QMatrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16));
 +    CPP_TEST(QQmlFontValueType, QFont("Helvetica"));
 +
 +}
 +
 +void tst_qqmlvaluetypes::enums()
 +{
 +    {
 +    QQmlComponent component(&engine, testFileUrl("enums.1.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QVERIFY(object->font().capitalization() == QFont::AllUppercase);
 +    delete object;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("enums.2.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QVERIFY(object->font().capitalization() == QFont::AllUppercase);
 +    delete object;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("enums.3.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QVERIFY(object->font().capitalization() == QFont::AllUppercase);
 +    delete object;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("enums.4.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QVERIFY(object->font().capitalization() == QFont::AllUppercase);
 +    delete object;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("enums.5.qml"));
 +    MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
 +    QVERIFY(object != 0);
 +    QVERIFY(object->font().capitalization() == QFont::AllUppercase);
 +    delete object;
 +    }
 +}
 +
 +// Tests switching between "conflicting" bindings (eg. a binding on the core
 +// property, to a binding on the value-type sub-property)
 +void tst_qqmlvaluetypes::conflictingBindings()
 +{
 +    {
 +    QQmlComponent component(&engine, testFileUrl("conflicting.1.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
 +
 +    QMetaObject::invokeMethod(object, "toggle");
 +
 +    QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
 +
 +    QMetaObject::invokeMethod(object, "toggle");
 +
 +    QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
 +
 +    delete object;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("conflicting.2.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
 +
 +    QMetaObject::invokeMethod(object, "toggle");
 +
 +    QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
 +
 +    QMetaObject::invokeMethod(object, "toggle");
 +
 +    QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
 +
 +    delete object;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("conflicting.3.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
 +
 +    QMetaObject::invokeMethod(object, "toggle");
 +
 +    QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 24);
 +
 +    QMetaObject::invokeMethod(object, "toggle");
 +
 +    QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
 +
 +    delete object;
 +    }
 +}
 +
 +void tst_qqmlvaluetypes::returnValues()
 +{
 +    QQmlComponent component(&engine, testFileUrl("returnValues.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test1").toBool(), true);
 +    QCOMPARE(object->property("test2").toBool(), true);
 +    QCOMPARE(object->property("size").toSize(), QSize(13, 14));
 +
 +    delete object;
 +}
 +
 +void tst_qqmlvaluetypes::varAssignment()
 +{
 +    QQmlComponent component(&engine, testFileUrl("varAssignment.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("x").toInt(), 1);
 +    QCOMPARE(object->property("y").toInt(), 2);
 +    QCOMPARE(object->property("z").toInt(), 3);
 +
 +    delete object;
 +}
 +
 +// Test bindings splice together correctly
 +void tst_qqmlvaluetypes::bindingsSpliceCorrectly()
 +{
 +    {
 +    QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.1.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.2.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +    }
 +
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.3.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.4.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +    }
 +
 +    {
 +    QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.5.qml"));
 +    QObject *object = component.create();
 +    QVERIFY(object != 0);
 +
 +    QCOMPARE(object->property("test").toBool(), true);
 +
 +    delete object;
 +    }
 +}
 +
++void tst_qqmlvaluetypes::nonValueTypeComparison()
++{
++    QQmlComponent component(&engine, testFileUrl("nonValueTypeComparison.qml"));
++    QObject *object = component.create();
++    QVERIFY(object != 0);
++
++    QCOMPARE(object->property("test1").toBool(), true);
++    QCOMPARE(object->property("test2").toBool(), true);
++
++    delete object;
++}
++
 +QTEST_MAIN(tst_qqmlvaluetypes)
 +
 +#include "tst_qqmlvaluetypes.moc"
index a6d90cf,0000000..3761929
mode 100644,000000..100644
--- /dev/null
@@@ -1,179 -1,0 +1,179 @@@
-     QCOMPARE(removeStart, 0);
-     QCOMPARE(removeEnd, count-1);
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <qtest.h>
 +#include <QtTest/QSignalSpy>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtCore/qdir.h>
 +#include <QtCore/qfile.h>
 +#include <QtCore/qabstractitemmodel.h>
 +#include <QDebug>
 +#include "../../shared/util.h"
 +
 +// From qquickfolderlistmodel.h
 +const int FileNameRole = Qt::UserRole+1;
 +const int FilePathRole = Qt::UserRole+2;
 +enum SortField { Unsorted, Name, Time, Size, Type };
 +
 +class tst_qquickfolderlistmodel : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_qquickfolderlistmodel() : removeStart(0), removeEnd(0) {}
 +
 +public slots:
 +    void removed(const QModelIndex &, int start, int end) {
 +        removeStart = start;
 +        removeEnd = end;
 +    }
 +
 +private slots:
 +    void basicProperties();
 +    void resetFiltering();
 +    void refresh();
 +
 +private:
 +    void checkNoErrors(const QQmlComponent& component);
 +    QQmlEngine engine;
 +
 +    int removeStart;
 +    int removeEnd;
 +};
 +
 +void tst_qquickfolderlistmodel::checkNoErrors(const QQmlComponent& component)
 +{
 +    // Wait until the component is ready
 +    QTRY_VERIFY(component.isReady() || component.isError());
 +
 +    if (component.isError()) {
 +        QList<QQmlError> errors = component.errors();
 +        for (int ii = 0; ii < errors.count(); ++ii) {
 +            const QQmlError &error = errors.at(ii);
 +            QByteArray errorStr = QByteArray::number(error.line()) + ":" +
 +                                  QByteArray::number(error.column()) + ":" +
 +                                  error.description().toUtf8();
 +            qWarning() << errorStr;
 +        }
 +    }
 +    QVERIFY(!component.isError());
 +}
 +
 +void tst_qquickfolderlistmodel::basicProperties()
 +{
 +    QQmlComponent component(&engine, testFileUrl("basic.qml"));
 +    checkNoErrors(component);
 +
 +    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
 +    QVERIFY(flm != 0);
 +
 +    flm->setProperty("folder", dataDirectoryUrl());
 +    QTRY_COMPARE(flm->property("count").toInt(),4); // wait for refresh
 +    QCOMPARE(flm->property("folder").toUrl(), dataDirectoryUrl());
 +    QCOMPARE(flm->property("parentFolder").toUrl(), QUrl::fromLocalFile(QDir(directory()).canonicalPath()));
 +    QCOMPARE(flm->property("sortField").toInt(), int(Name));
 +    QCOMPARE(flm->property("nameFilters").toStringList(), QStringList() << "*.qml");
 +    QCOMPARE(flm->property("sortReversed").toBool(), false);
 +    QCOMPARE(flm->property("showDirs").toBool(), true);
 +    QCOMPARE(flm->property("showDotAndDotDot").toBool(), false);
 +    QCOMPARE(flm->property("showOnlyReadable").toBool(), false);
 +    QCOMPARE(flm->data(flm->index(0),FileNameRole).toString(), QLatin1String("basic.qml"));
 +    QCOMPARE(flm->data(flm->index(1),FileNameRole).toString(), QLatin1String("dummy.qml"));    
 +    
 +    flm->setProperty("folder",QUrl::fromLocalFile(""));
 +    QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile(""));
 +}
 +
 +void tst_qquickfolderlistmodel::resetFiltering()
 +{
 +    // see QTBUG-17837
 +    QQmlComponent component(&engine, testFileUrl("resetFiltering.qml"));
 +    checkNoErrors(component);
 +
 +    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
 +    QVERIFY(flm != 0);
 +
 +    connect(flm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)),
 +            this, SLOT(removed(const QModelIndex&,int,int)));
 +
 +    flm->setProperty("folder", testFileUrl("resetfiltering"));
 +    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible
 +    int count = flm->rowCount();
 +    QCOMPARE(removeStart, 0);
 +    QCOMPARE(removeEnd, count-1);
 +
 +    flm->setProperty("folder", testFileUrl("resetfiltering/innerdir"));
 +    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test2.txt" visible
 +    count = flm->rowCount();
 +    QCOMPARE(removeStart, 0);
 +    QCOMPARE(removeEnd, count-1);
 +
 +    flm->setProperty("folder", testFileUrl("resetfiltering"));
 +    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible
 +    count = flm->rowCount();
 +    QCOMPARE(removeStart, 0);
 +    QCOMPARE(removeEnd, count-1);
 +}
 +
 +void tst_qquickfolderlistmodel::refresh()
 +{
 +    QQmlComponent component(&engine, testFileUrl("basic.qml"));
 +    checkNoErrors(component);
 +
 +    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
 +    QVERIFY(flm != 0);
 +
 +    flm->setProperty("folder", dataDirectoryUrl());
 +    QTRY_COMPARE(flm->property("count").toInt(),4); // wait for refresh
 +
 +    int count = flm->rowCount();
 +
 +    connect(flm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)),
 +            this, SLOT(removed(const QModelIndex&,int,int)));
 +
 +    flm->setProperty("sortReversed", true);
 +
++    QTRY_COMPARE(removeStart, 0);
++    QTRY_COMPARE(removeEnd, count-1); // wait for refresh
 +}
 +
 +QTEST_MAIN(tst_qquickfolderlistmodel)
 +
 +#include "tst_qquickfolderlistmodel.moc"
index 559abf7,0000000..4e3e71f
mode 100644,000000..100644
--- /dev/null
@@@ -1,353 -1,0 +1,371 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <qtest.h>
 +#include <QtCore/qobject.h>
 +#include <QtCore/qfileinfo.h>
 +#include <QtCore/qdir.h>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtCore/qdebug.h>
++#include <QtGui/qcolor.h>
 +
 +#include <private/qv4compiler_p.h>
 +
 +#include "../../shared/util.h"
 +#include "testtypes.h"
 +
 +class tst_v4 : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_v4() {}
 +
 +private slots:
 +    void initTestCase();
 +
 +    void unnecessaryReeval();
 +    void logicalOr();
 +    void nestedLogicalOr();
 +    void conditionalExpr();
 +    void qtscript();
 +    void qtscript_data();
 +    void nestedObjectAccess();
 +    void subscriptionsInConditionalExpressions();
 +    void qtbug_21883();
 +    void qtbug_22816();
 +    void stringComparison();
 +    void unaryMinus();
 +    void unaryPlus();
++    void colorType();
 +
 +private:
 +    QQmlEngine engine;
 +};
 +
 +void tst_v4::initTestCase()
 +{
 +    QQmlDataTest::initTestCase();
 +    registerTypes();
 +}
 +
 +static int v4ErrorsMsgCount = 0;
 +static void v4ErrorsMsgHandler(QtMsgType, const char *message)
 +{
 +    QByteArray m(message);
 +    if (m.contains("QV4"))
 +        v4ErrorsMsgCount++;
 +}
 +
 +void tst_v4::qtscript()
 +{
 +    QFETCH(QString, file);
 +    QV4Compiler::enableBindingsTest(true);
 +
 +    QQmlComponent component(&engine, testFileUrl(file));
 +
 +    v4ErrorsMsgCount = 0;
 +    QtMsgHandler old = qInstallMsgHandler(v4ErrorsMsgHandler);
 +
 +    QObject *o = component.create();
 +    delete o;
 +
 +    qInstallMsgHandler(old);
 +
 +    QCOMPARE(v4ErrorsMsgCount, 0);
 +
 +    QV4Compiler::enableBindingsTest(false);
 +}
 +
 +void tst_v4::qtscript_data()
 +{
 +    QTest::addColumn<QString>("file");
 +
 +    QTest::newRow("qreal -> int rounding") << "qrealToIntRounding.qml";
 +    QTest::newRow("exception on fetch") << "fetchException.qml";
 +    QTest::newRow("logical or") << "logicalOr.qml";
 +    QTest::newRow("conditional expressions") << "conditionalExpr.qml";
 +    QTest::newRow("double bool jump") << "doubleBoolJump.qml";
 +    QTest::newRow("unary minus") << "unaryMinus.qml";
 +    QTest::newRow("null qobject") << "nullQObject.qml";
 +}
 +
 +void tst_v4::unnecessaryReeval()
 +{
 +    QQmlComponent component(&engine, testFileUrl("unnecessaryReeval.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    ResultObject *ro = qobject_cast<ResultObject *>(o);
 +    QVERIFY(ro != 0);
 +
 +    QCOMPARE(ro->resultCounter(),  1);
 +    QCOMPARE(ro->result(), 19);
 +    ro->resetResultCounter();
 +
 +    ro->setProperty("b", 6);
 +
 +    QCOMPARE(ro->resultCounter(),  1);
 +    QCOMPARE(ro->result(), 6);
 +    ro->resetResultCounter();
 +
 +    ro->setProperty("a", 14);
 +
 +    QCOMPARE(ro->resultCounter(),  1);
 +    QCOMPARE(ro->result(), 7);
 +    ro->resetResultCounter();
 +
 +    ro->setProperty("b", 14);
 +    QCOMPARE(ro->resultCounter(),  0);
 +    QCOMPARE(ro->result(), 7);
 +
 +    delete o;
 +}
 +
 +void tst_v4::logicalOr()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("logicalOr.qml"));
 +
 +        QObject *o = component.create();
 +        QVERIFY(o != 0);
 +
 +        ResultObject *ro = qobject_cast<ResultObject *>(o);
 +        QVERIFY(ro != 0);
 +
 +        QCOMPARE(ro->result(), 0);
 +        delete o;
 +    }
 +
 +    {
 +        QQmlComponent component(&engine, testFileUrl("logicalOr.2.qml"));
 +
 +        QObject *o = component.create();
 +        QVERIFY(o != 0);
 +
 +        ResultObject *ro = qobject_cast<ResultObject *>(o);
 +        QVERIFY(ro != 0);
 +
 +        QCOMPARE(ro->result(), 1);
 +        delete o;
 +    }
 +}
 +
 +void tst_v4::nestedLogicalOr()
 +{
 +    //we are primarily testing that v4 does not get caught in a loop (QTBUG-24038)
 +    QQmlComponent component(&engine, testFileUrl("nestedLogicalOr.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    ResultObject *ro = qobject_cast<ResultObject *>(o);
 +    QVERIFY(ro != 0);
 +
 +    QCOMPARE(ro->result(), 1);
 +    delete o;
 +}
 +
 +void tst_v4::conditionalExpr()
 +{
 +    {
 +        QQmlComponent component(&engine, testFileUrl("conditionalExpr.qml"));
 +
 +        QObject *o = component.create();
 +        QVERIFY(o != 0);
 +
 +        ResultObject *ro = qobject_cast<ResultObject *>(o);
 +        QVERIFY(ro != 0);
 +
 +        QCOMPARE(ro->result(), 0);
 +        delete o;
 +    }
 +}
 +
 +// This would previously use the metaObject of the root element to result the nested access.
 +// That is, the index for accessing "result" would have been RootObject::result, instead of
 +// NestedObject::result.
 +void tst_v4::nestedObjectAccess()
 +{
 +    QQmlComponent component(&engine, testFileUrl("nestedObjectAccess.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    ResultObject *ro = qobject_cast<ResultObject *>(o);
 +    QVERIFY(ro != 0);
 +
 +    QCOMPARE(ro->result(), 37);
 +
 +    delete o;
 +}
 +
 +void tst_v4::subscriptionsInConditionalExpressions()
 +{
 +    QQmlComponent component(&engine, testFileUrl("subscriptionsInConditionalExpressions.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QObject *ro = qobject_cast<QObject *>(o);
 +    QVERIFY(ro != 0);
 +
 +    QCOMPARE(ro->property("result").toReal(), qreal(2));
 +
 +    delete o;
 +}
 +
 +// Crash test
 +void tst_v4::qtbug_21883()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtbug_21883.qml"));
 +
 +    QString warning = component.url().toString() + ":4: Unable to assign null to ResultObject*";
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    delete o;
 +}
 +
 +void tst_v4::qtbug_22816()
 +{
 +    QQmlComponent component(&engine, testFileUrl("qtbug_22816.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test1").toBool(), false);
 +    QCOMPARE(o->property("test2").toBool(), false);
 +    delete o;
 +}
 +
 +void tst_v4::stringComparison()
 +{
 +    QQmlComponent component(&engine, testFileUrl("stringComparison.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +    QCOMPARE(o->property("test1").toBool(), true);
 +    QCOMPARE(o->property("test2").toBool(), true);
 +    QCOMPARE(o->property("test3").toBool(), true);
 +    QCOMPARE(o->property("test4").toBool(), true);
 +    QCOMPARE(o->property("test5").toBool(), true);
 +    QCOMPARE(o->property("test6").toBool(), true);
 +    QCOMPARE(o->property("test7").toBool(), true);
 +    QCOMPARE(o->property("test8").toBool(), true);
 +    QCOMPARE(o->property("test9").toBool(), true);
 +    QCOMPARE(o->property("test10").toBool(), true);
 +    QCOMPARE(o->property("test11").toBool(), true);
 +    QCOMPARE(o->property("test12").toBool(), true);
 +    QCOMPARE(o->property("test13").toBool(), true);
 +    QCOMPARE(o->property("test14").toBool(), true);
 +    QCOMPARE(o->property("test15").toBool(), true);
 +    QCOMPARE(o->property("test16").toBool(), true);
 +    QCOMPARE(o->property("test17").toBool(), true);
 +    QCOMPARE(o->property("test18").toBool(), true);
 +    QCOMPARE(o->property("test19").toBool(), true);
 +    QCOMPARE(o->property("test20").toBool(), true);
 +    QCOMPARE(o->property("test21").toBool(), true);
 +    QCOMPARE(o->property("test22").toBool(), true);
 +    delete o;
 +}
 +
 +void tst_v4::unaryMinus()
 +{
 +    QQmlComponent component(&engine, testFileUrl("unaryMinus.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test1").toReal(), qreal(-18));
 +    QCOMPARE(o->property("test2").toInt(), -18);
 +    QCOMPARE(o->property("test3").toReal(), qreal(3.7));
 +    QCOMPARE(o->property("test4").toInt(), 4);
 +    QCOMPARE(o->property("test5").toReal(), qreal(3.3));
 +    QCOMPARE(o->property("test6").toInt(), 3);
 +    QCOMPARE(o->property("test7").toReal(), qreal(7));
 +    QCOMPARE(o->property("test8").toInt(), 7);
 +    QCOMPARE(o->property("test9").toReal(), qreal(-4.4));
 +    QCOMPARE(o->property("test10").toInt(), -4);
 +
 +    delete o;
 +}
 +
 +void tst_v4::unaryPlus()
 +{
 +    QQmlComponent component(&engine, testFileUrl("unaryPlus.qml"));
 +
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    QCOMPARE(o->property("test1").toReal(), qreal(18));
 +    QCOMPARE(o->property("test2").toInt(), 18);
 +    QCOMPARE(o->property("test3").toReal(), qreal(-3.7));
 +    QCOMPARE(o->property("test4").toInt(), -4);
 +    QCOMPARE(o->property("test5").toReal(), qreal(-3.3));
 +    QCOMPARE(o->property("test6").toInt(), -3);
 +    QCOMPARE(o->property("test7").toReal(), qreal(-7));
 +    QCOMPARE(o->property("test8").toInt(), -7);
 +    QCOMPARE(o->property("test9").toReal(), qreal(4.4));
 +    QCOMPARE(o->property("test10").toInt(), 4);
 +
 +    delete o;
 +}
 +
++void tst_v4::colorType()
++{
++    QQmlComponent component(&engine, testFileUrl("colorType.qml"));
++
++    QObject *o = component.create();
++    QVERIFY(o != 0);
++    QCOMPARE(o->property("test1").value<QColor>(), QColor("red"));
++    QCOMPARE(o->property("test2").value<QColor>(), QColor("red"));
++    QCOMPARE(o->property("test3").value<QColor>(), QColor("red"));
++    QCOMPARE(o->property("test4").toBool(), true);
++    QCOMPARE(o->property("test5").toBool(), true);
++    QCOMPARE(o->property("test6").toBool(), true);
++    QCOMPARE(o->property("test7").toBool(), true);
++    delete o;
++}
++
 +QTEST_MAIN(tst_v4)
 +
 +#include "tst_v4.moc"
index 24a60cb,0000000..482053e
mode 100644,000000..100644
--- /dev/null
@@@ -1,307 -1,0 +1,299 @@@
-     // Add directories you want excluded here
-     excludedDirs << "examples/qml/text/fonts"; // QTBUG-21415
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include <qtest.h>
 +#include <QLibraryInfo>
 +#include <QDir>
 +#include <QProcess>
 +#include <QDebug>
 +#include <QtQuick/QQuickItem>
 +#include <QtQuick/QQuickView>
 +#include <QQmlComponent>
 +#include <QQmlEngine>
 +#include <QQmlError>
 +
 +static QtMsgHandler testlibMsgHandler = 0;
 +void msgHandlerFilter(QtMsgType type, const char *msg)
 +{
 +    if (type == QtCriticalMsg || type == QtFatalMsg)
 +        (*testlibMsgHandler)(type, msg);
 +}
 +
 +class tst_examples : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    tst_examples();
 +
 +private slots:
 +    void init();
 +    void cleanup();
 +
 +    void sgexamples_data();
 +    void sgexamples();
 +    void sgsnippets_data();
 +    void sgsnippets();
 +
 +    void namingConvention();
 +private:
 +    QStringList excludedDirs;
 +    QStringList excludedFiles;
 +
 +    void namingConvention(const QDir &);
 +    QStringList findQmlFiles(const QDir &);
 +
 +    QQmlEngine engine;
 +};
 +
 +tst_examples::tst_examples()
 +{
 +    // Add files to exclude here
 +    excludedFiles << "doc/src/snippets/qml/listmodel.qml"; //Just a ListModel, no root QQuickItem
 +
-     // Not run in QQuickView
-     excludedDirs << "examples/qml/qtquick1";
++    // Add directories you want excluded here (don't add examples/, because they install to examples/qtdeclarative/)
++    excludedDirs << "shared"; //Not an example
++    excludedDirs << "qtquick/text/fonts"; // QTBUG-21415
 +    excludedDirs << "doc/src/snippets/qml/path"; //No root QQuickItem
-     excludedDirs << "doc/src/snippets/qtquick1/visualdatamodel_rootindex";
-     excludedDirs << "doc/src/snippets/qtquick1/qtbinding";
-     excludedDirs << "doc/src/snippets/qtquick1/imports";
++    excludedDirs << "tutorials/gettingStartedQml"; //C++ example, but no cpp files in root dir
 +
 +    // These snippets are not expected to run on their own.
 +    excludedDirs << "doc/src/snippets/qml/visualdatamodel_rootindex";
 +    excludedDirs << "doc/src/snippets/qml/qtbinding";
 +    excludedDirs << "doc/src/snippets/qml/imports";
-     excludedDirs << "examples/qml/modelviews/webview";
-     excludedDirs << "examples/qml/webbrowser";
 +
 +#ifdef QT_NO_WEBKIT
-     excludedDirs << "doc/src/snippets/qtquick1/webview";
++    excludedDirs << "qtquick/modelviews/webview";
++    excludedDirs << "demos/webbrowser";
 +    excludedDirs << "doc/src/snippets/qml/webview";
-     excludedDirs << "examples/qml/xml/xmldata";
-     excludedDirs << "examples/qml/twitter";
-     excludedDirs << "examples/qml/flickr";
-     excludedDirs << "examples/qml/photoviewer";
 +#endif
 +
 +#ifdef QT_NO_XMLPATTERNS
-     QString examples = QLatin1String(SRCDIR) + "/../../../../examples/qml/";
-     QString tutorials = QLatin1String(SRCDIR) + "/../../../../examples/tutorials/"; //Only qml tutorials since modularization
++    excludedDirs << "demos/twitter";
++    excludedDirs << "demos/flickr";
++    excludedDirs << "demos/photoviewer";
 +#endif
 +}
 +
 +void tst_examples::init()
 +{
 +    if (!qstrcmp(QTest::currentTestFunction(), "sgsnippets"))
 +        testlibMsgHandler = qInstallMsgHandler(msgHandlerFilter);
 +}
 +
 +void tst_examples::cleanup()
 +{
 +    if (!qstrcmp(QTest::currentTestFunction(), "sgsnippets"))
 +        qInstallMsgHandler(testlibMsgHandler);
 +}
 +
 +/*
 +This tests that the examples follow the naming convention required
 +to have them tested by the examples() test.
 +*/
 +void tst_examples::namingConvention(const QDir &d)
 +{
 +    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
 +        QString s = excludedDirs.at(ii);
 +        if (d.absolutePath().endsWith(s))
 +            return;
 +    }
 +
 +    QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
 +                                    QDir::Files);
 +
 +    bool seenQml = !files.isEmpty();
 +    bool seenLowercase = false;
 +
 +    foreach (const QString &file, files) {
 +        if (file.at(0).isLower())
 +            seenLowercase = true;
 +    }
 +
 +    if (!seenQml) {
 +        QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
 +                QDir::NoSymLinks);
 +        foreach (const QString &dir, dirs) {
 +            QDir sub = d;
 +            sub.cd(dir);
 +            namingConvention(sub);
 +        }
 +    } else if(!seenLowercase) {
 +        QFAIL(qPrintable(QString(
 +            "Directory %1 violates naming convention; expected at least one qml file "
 +            "starting with lower case, got: %2"
 +        ).arg(d.absolutePath()).arg(files.join(","))));
 +    }
 +}
 +
 +void tst_examples::namingConvention()
 +{
 +    QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
 +
 +    namingConvention(QDir(examples));
 +}
 +
 +QStringList tst_examples::findQmlFiles(const QDir &d)
 +{
 +    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
 +        QString s = excludedDirs.at(ii);
 +        if (d.absolutePath().endsWith(s))
 +            return QStringList();
 +    }
 +
 +    QStringList rv;
 +
 +    QStringList cppfiles = d.entryList(QStringList() << QLatin1String("*.cpp"), QDir::Files);
 +    if (cppfiles.isEmpty()) {
 +        QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
 +                                        QDir::Files);
 +        foreach (const QString &file, files) {
 +            if (file.at(0).isLower()) {
 +                bool superContinue = false;
 +                for (int ii = 0; ii < excludedFiles.count(); ++ii) {
 +                    QString e = excludedFiles.at(ii);
 +                    if (d.absoluteFilePath(file).endsWith(e)) {
 +                        superContinue = true;
 +                        break;
 +                    }
 +                }
 +                if (superContinue)
 +                    continue;
 +                rv << d.absoluteFilePath(file);
 +            }
 +        }
 +    }
 +
 +
 +    QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
 +                                   QDir::NoSymLinks);
 +    foreach (const QString &dir, dirs) {
 +        QDir sub = d;
 +        sub.cd(dir);
 +        rv << findQmlFiles(sub);
 +    }
 +
 +    return rv;
 +}
 +
 +/*
 +This test runs all the examples in the QtQml UI source tree and ensures
 +that they start and exit cleanly.
 +
 +Examples are any .qml files under the examples/ directory that start
 +with a lower case letter.
 +*/
 +void tst_examples::sgexamples_data()
 +{
 +    QTest::addColumn<QString>("file");
 +
-     files << findQmlFiles(QDir(tutorials));
++    QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";
 +
 +    QStringList files;
 +    files << findQmlFiles(QDir(examples));
 +
 +    foreach (const QString &file, files)
 +        QTest::newRow(qPrintable(file)) << file;
 +}
 +
 +void tst_examples::sgexamples()
 +{
 +    QFETCH(QString, file);
 +
 +    QQmlComponent component(&engine, QUrl::fromLocalFile(file));
 +    if (component.status() == QQmlComponent::Error)
 +        qWarning() << component.errors();
 +    QCOMPARE(component.status(), QQmlComponent::Ready);
 +
 +    QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
 +    QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
 +    if (!root)
 +        component.completeCreate();
 +    QVERIFY(root);
 +
 +    QQuickCanvas canvas;
 +    root->setParentItem(canvas.rootItem());
 +    component.completeCreate();
 +    canvas.show();
 +
 +    QTest::qWaitForWindowShown(&canvas);
 +
 +}
 +
 +void tst_examples::sgsnippets_data()
 +{
 +    QTest::addColumn<QString>("file");
 +
 +    QString snippets = QLatin1String(SRCDIR) + "/../../../../doc/src/snippets/qml";
 +
 +    QStringList files;
 +    files << findQmlFiles(QDir(snippets));
 +
 +    foreach (const QString &file, files)
 +        QTest::newRow(qPrintable(file)) << file;
 +}
 +
 +void tst_examples::sgsnippets()
 +{
 +    QFETCH(QString, file);
 +
 +    QQmlComponent component(&engine, QUrl::fromLocalFile(file));
 +    if (component.status() == QQmlComponent::Error)
 +        qWarning() << component.errors();
 +    QCOMPARE(component.status(), QQmlComponent::Ready);
 +
 +    QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
 +    QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
 +    if (!root)
 +        component.completeCreate();
 +    QVERIFY(root);
 +
 +    QQuickCanvas canvas;
 +    root->setParentItem(canvas.rootItem());
 +    component.completeCreate();
 +    canvas.show();
 +
 +    QTest::qWaitForWindowShown(&canvas);
 +
 +}
 +
 +QTEST_MAIN(tst_examples)
 +
 +#include "tst_examples.moc"
index 749b11f,0000000..dd1f9f7
mode 100644,000000..100644
--- /dev/null
@@@ -1,669 -1,0 +1,710 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <qtest.h>
 +#include <QSignalSpy>
 +#include <private/qquickitem_p.h>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtQuick/qquickview.h>
 +#include <QtQuick/private/qquickrectangle_p.h>
 +#include <QtQuick/private/qquicktext_p.h>
 +#include <QtQuick/private/qquickanchors_p_p.h>
 +#include <QtQuick/private/qquickitem_p.h>
 +#include "../../shared/util.h"
 +#include "../shared/visualtestutil.h"
 +
 +Q_DECLARE_METATYPE(QQuickAnchors::Anchor)
 +Q_DECLARE_METATYPE(QQuickAnchorLine::AnchorLine)
 +
 +using namespace QQuickVisualTestUtil;
 +
 +class tst_qquickanchors : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_qquickanchors() {}
 +
 +private slots:
 +    void basicAnchors();
 +    void basicAnchorsRTL();
 +    void loops();
 +    void illegalSets();
 +    void illegalSets_data();
 +    void reset();
 +    void reset_data();
 +    void resetConvenience();
 +    void nullItem();
 +    void nullItem_data();
 +    void crash1();
 +    void centerIn();
 +    void centerInRTL();
 +    void centerInRotation();
 +    void hvCenter();
 +    void hvCenterRTL();
 +    void fill();
 +    void fillRTL();
 +    void margins();
 +    void marginsRTL();
++    void stretch();
 +};
 +
 +void tst_qquickanchors::basicAnchors()
 +{
 +    QQuickView *view = new QQuickView;
 +    view->setSource(testFileUrl("anchors.qml"));
 +
 +    qApp->processEvents();
 +
 +    //sibling horizontal
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect1"))->x(), 26.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect2"))->x(), 122.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect3"))->x(), 74.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect4"))->x(), 16.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect5"))->x(), 112.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect6"))->x(), 64.0);
 +
 +    //parent horizontal
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect7"))->x(), 0.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect8"))->x(), 240.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect9"))->x(), 120.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect10"))->x(), -10.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect11"))->x(), 230.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect12"))->x(), 110.0);
 +
 +    //vertical
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect13"))->y(), 20.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect14"))->y(), 155.0);
 +
 +    //stretch
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect15"))->x(), 26.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect15"))->width(), 96.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect16"))->x(), 26.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect16"))->width(), 192.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect17"))->x(), -70.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect17"))->width(), 192.0);
 +
 +    //vertical stretch
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect18"))->y(), 20.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect18"))->height(), 40.0);
 +
 +    //more parent horizontal
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect19"))->x(), 115.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect20"))->x(), 235.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect21"))->x(), -5.0);
 +
 +    //centerIn
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect22"))->x(), 69.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect22"))->y(), 5.0);
 +
 +     //margins
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->x(), 31.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->y(), 5.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->width(), 86.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->height(), 10.0);
 +
 +    // offsets
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect24"))->x(), 26.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect25"))->y(), 60.0);
 +    QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect26"))->y(), 5.0);
 +
 +    //baseline
 +    QQuickText *text1 = findItem<QQuickText>(view->rootObject(), QLatin1String("text1"));
 +    QQuickText *text2 = findItem<QQuickText>(view->rootObject(), QLatin1String("text2"));
 +    QCOMPARE(text1->y(), text2->y());
 +
 +    delete view;
 +}
 +
 +QQuickItem* childItem(QQuickItem *parentItem, const char * itemString) {
 +    return findItem<QQuickItem>(parentItem, QLatin1String(itemString));
 +}
 +
 +qreal offsetMasterRTL(QQuickItem *rootItem, const char * itemString) {
 +    QQuickItem* masterItem = findItem<QQuickItem>(rootItem,  QLatin1String("masterRect"));
 +    return masterItem->width()+2*masterItem->x()-findItem<QQuickItem>(rootItem,  QLatin1String(itemString))->width();
 +}
 +
 +qreal offsetParentRTL(QQuickItem *rootItem, const char * itemString) {
 +    return rootItem->width()+2*rootItem->x()-findItem<QQuickItem>(rootItem,  QLatin1String(itemString))->width();
 +}
 +
 +void mirrorAnchors(QQuickItem *item) {
 +    QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
 +    itemPrivate->setLayoutMirror(true);
 +}
 +
 +void tst_qquickanchors::basicAnchorsRTL()
 +{
 +    QQuickView *view = new QQuickView;
 +    view->setSource(testFileUrl("anchors.qml"));
 +
 +    qApp->processEvents();
 +
 +    QQuickItem* rootItem = qobject_cast<QQuickItem*>(view->rootObject());
 +    foreach (QObject *child, rootItem->children()) {
 +        bool mirrored = QQuickItemPrivate::get(qobject_cast<QQuickItem*>(child))->anchors()->property("mirrored").toBool();
 +        QCOMPARE(mirrored, false);
 +    }
 +
 +    foreach (QObject *child, rootItem->children())
 +        mirrorAnchors(qobject_cast<QQuickItem*>(child));
 +
 +    foreach (QObject *child, rootItem->children()) {
 +        bool mirrored = QQuickItemPrivate::get(qobject_cast<QQuickItem*>(child))->anchors()->property("mirrored").toBool();
 +        QCOMPARE(mirrored, true);
 +    }
 +
 +    //sibling horizontal
 +    QCOMPARE(childItem(rootItem, "rect1")->x(), offsetMasterRTL(rootItem, "rect1")-26.0);
 +    QCOMPARE(childItem(rootItem, "rect2")->x(), offsetMasterRTL(rootItem, "rect2")-122.0);
 +    QCOMPARE(childItem(rootItem, "rect3")->x(), offsetMasterRTL(rootItem, "rect3")-74.0);
 +    QCOMPARE(childItem(rootItem, "rect4")->x(), offsetMasterRTL(rootItem, "rect4")-16.0);
 +    QCOMPARE(childItem(rootItem, "rect5")->x(), offsetMasterRTL(rootItem, "rect5")-112.0);
 +    QCOMPARE(childItem(rootItem, "rect6")->x(), offsetMasterRTL(rootItem, "rect6")-64.0);
 +
 +    //parent horizontal
 +    QCOMPARE(childItem(rootItem, "rect7")->x(), offsetParentRTL(rootItem, "rect7")-0.0);
 +    QCOMPARE(childItem(rootItem, "rect8")->x(), offsetParentRTL(rootItem, "rect8")-240.0);
 +    QCOMPARE(childItem(rootItem, "rect9")->x(), offsetParentRTL(rootItem, "rect9")-120.0);
 +    QCOMPARE(childItem(rootItem, "rect10")->x(), offsetParentRTL(rootItem, "rect10")+10.0);
 +    QCOMPARE(childItem(rootItem, "rect11")->x(), offsetParentRTL(rootItem, "rect11")-230.0);
 +    QCOMPARE(childItem(rootItem, "rect12")->x(), offsetParentRTL(rootItem, "rect12")-110.0);
 +
 +    //vertical
 +    QCOMPARE(childItem(rootItem, "rect13")->y(), 20.0);
 +    QCOMPARE(childItem(rootItem, "rect14")->y(), 155.0);
 +
 +    //stretch
 +    QCOMPARE(childItem(rootItem, "rect15")->x(), offsetMasterRTL(rootItem, "rect15")-26.0);
 +    QCOMPARE(childItem(rootItem, "rect15")->width(), 96.0);
 +    QCOMPARE(childItem(rootItem, "rect16")->x(), offsetMasterRTL(rootItem, "rect16")-26.0);
 +    QCOMPARE(childItem(rootItem, "rect16")->width(), 192.0);
 +    QCOMPARE(childItem(rootItem, "rect17")->x(), offsetMasterRTL(rootItem, "rect17")+70.0);
 +    QCOMPARE(childItem(rootItem, "rect17")->width(), 192.0);
 +
 +    //vertical stretch
 +    QCOMPARE(childItem(rootItem, "rect18")->y(), 20.0);
 +    QCOMPARE(childItem(rootItem, "rect18")->height(), 40.0);
 +
 +    //more parent horizontal
 +    QCOMPARE(childItem(rootItem, "rect19")->x(), offsetParentRTL(rootItem, "rect19")-115.0);
 +    QCOMPARE(childItem(rootItem, "rect20")->x(), offsetParentRTL(rootItem, "rect20")-235.0);
 +    QCOMPARE(childItem(rootItem, "rect21")->x(), offsetParentRTL(rootItem, "rect21")+5.0);
 +
 +    //centerIn
 +    QCOMPARE(childItem(rootItem, "rect22")->x(), offsetMasterRTL(rootItem, "rect22")-69.0);
 +    QCOMPARE(childItem(rootItem, "rect22")->y(), 5.0);
 +
 +     //margins
 +    QCOMPARE(childItem(rootItem, "rect23")->x(), offsetMasterRTL(rootItem, "rect23")-31.0);
 +    QCOMPARE(childItem(rootItem, "rect23")->y(), 5.0);
 +    QCOMPARE(childItem(rootItem, "rect23")->width(), 86.0);
 +    QCOMPARE(childItem(rootItem, "rect23")->height(), 10.0);
 +
 +    // offsets
 +    QCOMPARE(childItem(rootItem, "rect24")->x(), offsetMasterRTL(rootItem, "rect24")-26.0);
 +    QCOMPARE(childItem(rootItem, "rect25")->y(), 60.0);
 +    QCOMPARE(childItem(rootItem, "rect26")->y(), 5.0);
 +
 +    //baseline
 +    QQuickText *text1 = findItem<QQuickText>(rootItem, QLatin1String("text1"));
 +    QQuickText *text2 = findItem<QQuickText>(rootItem, QLatin1String("text2"));
 +    QCOMPARE(text1->y(), text2->y());
 +
 +    delete view;
 +}
 +
 +// mostly testing that we don't crash
 +void tst_qquickanchors::loops()
 +{
 +    {
 +        QUrl source(testFileUrl("loop1.qml"));
 +
 +        QString expect = source.toString() + ":6:5: QML Text: Possible anchor loop detected on horizontal anchor.";
 +        QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
 +        QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
 +
 +        QQuickView *view = new QQuickView;
 +        view->setSource(source);
 +        qApp->processEvents();
 +
 +        delete view;
 +    }
 +
 +    {
 +        QUrl source(testFileUrl("loop2.qml"));
 +
 +        QString expect = source.toString() + ":8:3: QML Image: Possible anchor loop detected on horizontal anchor.";
 +        QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
 +
 +        QQuickView *view = new QQuickView;
 +        view->setSource(source);
 +        qApp->processEvents();
 +
 +        delete view;
 +    }
 +}
 +
 +void tst_qquickanchors::illegalSets()
 +{
 +    QFETCH(QString, qml);
 +    QFETCH(QString, warning);
 +
 +    QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
 +
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine);
 +    component.setData(QByteArray("import QtQuick 2.0\n" + qml.toUtf8()), QUrl::fromLocalFile(""));
 +    if (!component.isReady())
 +        qWarning() << "Test errors:" << component.errors();
 +    QVERIFY(component.isReady());
 +    QObject *o = component.create();
 +    delete o;
 +}
 +
 +void tst_qquickanchors::illegalSets_data()
 +{
 +    QTest::addColumn<QString>("qml");
 +    QTest::addColumn<QString>("warning");
 +
 +    QTest::newRow("H - too many anchors")
 +        << "Rectangle { id: rect; Rectangle { anchors.left: rect.left; anchors.right: rect.right; anchors.horizontalCenter: rect.horizontalCenter } }"
 +        << "file::2:23: QML Rectangle: Cannot specify left, right, and hcenter anchors.";
 +
 +    foreach (const QString &side, QStringList() << "left" << "right") {
 +        QTest::newRow("H - anchor to V")
 +            << QString("Rectangle { Rectangle { anchors.%1: parent.top } }").arg(side)
 +            << "file::2:13: QML Rectangle: Cannot anchor a horizontal edge to a vertical edge.";
 +
 +        QTest::newRow("H - anchor to non parent/sibling")
 +            << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
 +            << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
 +
 +        QTest::newRow("H - anchor to self")
 +            << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
 +            << "file::2:1: QML Rectangle: Cannot anchor item to self.";
 +    }
 +
 +
 +    QTest::newRow("V - too many anchors")
 +        << "Rectangle { id: rect; Rectangle { anchors.top: rect.top; anchors.bottom: rect.bottom; anchors.verticalCenter: rect.verticalCenter } }"
 +        << "file::2:23: QML Rectangle: Cannot specify top, bottom, and vcenter anchors.";
 +
 +    QTest::newRow("V - too many anchors with baseline")
 +        << "Rectangle { Text { id: text1; text: \"Hello\" } Text { anchors.baseline: text1.baseline; anchors.top: text1.top; } }"
 +        << "file::2:47: QML Text: Baseline anchor cannot be used in conjunction with top, bottom, or vcenter anchors.";
 +
 +    foreach (const QString &side, QStringList() << "top" << "bottom" << "baseline") {
 +
 +        QTest::newRow("V - anchor to H")
 +            << QString("Rectangle { Rectangle { anchors.%1: parent.left } }").arg(side)
 +            << "file::2:13: QML Rectangle: Cannot anchor a vertical edge to a horizontal edge.";
 +
 +        QTest::newRow("V - anchor to non parent/sibling")
 +            << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
 +            << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
 +
 +        QTest::newRow("V - anchor to self")
 +            << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
 +            << "file::2:1: QML Rectangle: Cannot anchor item to self.";
 +    }
 +
 +
 +    QTest::newRow("centerIn - anchor to non parent/sibling")
 +        << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.centerIn: rect} }"
 +        << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
 +
 +
 +    QTest::newRow("fill - anchor to non parent/sibling")
 +        << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.fill: rect} }"
 +        << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
 +}
 +
 +void tst_qquickanchors::reset()
 +{
 +    QFETCH(QString, side);
 +    QFETCH(QQuickAnchorLine::AnchorLine, anchorLine);
 +    QFETCH(QQuickAnchors::Anchor, usedAnchor);
 +
 +    QQuickItem *baseItem = new QQuickItem;
 +
 +    QQuickAnchorLine anchor;
 +    anchor.item = baseItem;
 +    anchor.anchorLine = anchorLine;
 +
 +    QQuickItem *item = new QQuickItem;
 +    QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
 +
 +    const QMetaObject *meta = itemPrivate->anchors()->metaObject();
 +    QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
 +
 +    QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchor)));
 +    QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), true);
 +
 +    QVERIFY(p.reset(itemPrivate->anchors()));
 +    QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), false);
 +
 +    delete item;
 +    delete baseItem;
 +}
 +
 +void tst_qquickanchors::reset_data()
 +{
 +    QTest::addColumn<QString>("side");
 +    QTest::addColumn<QQuickAnchorLine::AnchorLine>("anchorLine");
 +    QTest::addColumn<QQuickAnchors::Anchor>("usedAnchor");
 +
 +    QTest::newRow("left") << "left" << QQuickAnchorLine::Left << QQuickAnchors::LeftAnchor;
 +    QTest::newRow("top") << "top" << QQuickAnchorLine::Top << QQuickAnchors::TopAnchor;
 +    QTest::newRow("right") << "right" << QQuickAnchorLine::Right << QQuickAnchors::RightAnchor;
 +    QTest::newRow("bottom") << "bottom" << QQuickAnchorLine::Bottom << QQuickAnchors::BottomAnchor;
 +
 +    QTest::newRow("hcenter") << "horizontalCenter" << QQuickAnchorLine::HCenter << QQuickAnchors::HCenterAnchor;
 +    QTest::newRow("vcenter") << "verticalCenter" << QQuickAnchorLine::VCenter << QQuickAnchors::VCenterAnchor;
 +    QTest::newRow("baseline") << "baseline" << QQuickAnchorLine::Baseline << QQuickAnchors::BaselineAnchor;
 +}
 +
 +void tst_qquickanchors::resetConvenience()
 +{
 +    QQuickItem *baseItem = new QQuickItem;
 +    QQuickItem *item = new QQuickItem;
 +    QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
 +
 +    //fill
 +    itemPrivate->anchors()->setFill(baseItem);
 +    QVERIFY(itemPrivate->anchors()->fill() == baseItem);
 +    itemPrivate->anchors()->resetFill();
 +    QVERIFY(itemPrivate->anchors()->fill() == 0);
 +
 +    //centerIn
 +    itemPrivate->anchors()->setCenterIn(baseItem);
 +    QVERIFY(itemPrivate->anchors()->centerIn() == baseItem);
 +    itemPrivate->anchors()->resetCenterIn();
 +    QVERIFY(itemPrivate->anchors()->centerIn() == 0);
 +
 +    delete item;
 +    delete baseItem;
 +}
 +
 +void tst_qquickanchors::nullItem()
 +{
 +    QFETCH(QString, side);
 +
 +    QQuickAnchorLine anchor;
 +    QQuickItem *item = new QQuickItem;
 +    QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
 +
 +    const QMetaObject *meta = itemPrivate->anchors()->metaObject();
 +    QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
 +
 +    QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML Item: Cannot anchor to a null item.");
 +    QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchor)));
 +
 +    delete item;
 +}
 +
 +void tst_qquickanchors::nullItem_data()
 +{
 +    QTest::addColumn<QString>("side");
 +
 +    QTest::newRow("left") << "left";
 +    QTest::newRow("top") << "top";
 +    QTest::newRow("right") << "right";
 +    QTest::newRow("bottom") << "bottom";
 +
 +    QTest::newRow("hcenter") << "horizontalCenter";
 +    QTest::newRow("vcenter") << "verticalCenter";
 +    QTest::newRow("baseline") << "baseline";
 +}
 +
 +//QTBUG-5428
 +void tst_qquickanchors::crash1()
 +{
 +    QUrl source(testFileUrl("crash1.qml"));
 +
 +    QQuickView *view = new QQuickView(source);
 +    qApp->processEvents();
 +
 +    delete view;
 +}
 +
 +void tst_qquickanchors::fill()
 +{
 +    QQuickView *view = new QQuickView(testFileUrl("fill.qml"));
 +
 +    qApp->processEvents();
 +    QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
 +    QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
++    QCOMPARE(rectPrivate->anchors()->leftMargin(), 10.0);
++    QCOMPARE(rectPrivate->anchors()->topMargin(), 30.0);
++    QCOMPARE(rectPrivate->anchors()->rightMargin(), 20.0);
++    QCOMPARE(rectPrivate->anchors()->bottomMargin(), 40.0);
 +    QCOMPARE(rect->x(), 0.0 + 10.0);
 +    QCOMPARE(rect->y(), 0.0 + 30.0);
 +    QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
 +    QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
 +    //Alter Offsets (tests QTBUG-6631)
 +    rectPrivate->anchors()->setLeftMargin(20.0);
 +    rectPrivate->anchors()->setRightMargin(0.0);
 +    rectPrivate->anchors()->setBottomMargin(0.0);
 +    rectPrivate->anchors()->setTopMargin(10.0);
++    QCOMPARE(rectPrivate->anchors()->leftMargin(), 20.0);
++    QCOMPARE(rectPrivate->anchors()->topMargin(), 10.0);
++    QCOMPARE(rectPrivate->anchors()->rightMargin(), 0.0);
++    QCOMPARE(rectPrivate->anchors()->bottomMargin(), 0.0);
 +    QCOMPARE(rect->x(), 0.0 + 20.0);
 +    QCOMPARE(rect->y(), 0.0 + 10.0);
 +    QCOMPARE(rect->width(), 200.0 - 20.0);
 +    QCOMPARE(rect->height(), 200.0 - 10.0);
 +
 +    delete view;
 +}
 +
 +void tst_qquickanchors::fillRTL()
 +{
 +    QQuickView *view = new QQuickView(testFileUrl("fill.qml"));
 +
 +    qApp->processEvents();
 +    QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
 +    QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
 +    mirrorAnchors(rect);
 +
 +    QCOMPARE(rect->x(), 0.0 + 20.0);
 +    QCOMPARE(rect->y(), 0.0 + 30.0);
 +    QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
 +    QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
 +    //Alter Offsets (tests QTBUG-6631)
 +    rectPrivate->anchors()->setLeftMargin(20.0);
 +    rectPrivate->anchors()->setRightMargin(0.0);
 +    rectPrivate->anchors()->setBottomMargin(0.0);
 +    rectPrivate->anchors()->setTopMargin(10.0);
 +    QCOMPARE(rect->x(), 0.0 + 0.0);
 +    QCOMPARE(rect->y(), 0.0 + 10.0);
 +    QCOMPARE(rect->width(), 200.0 - 20.0);
 +    QCOMPARE(rect->height(), 200.0 - 10.0);
 +
 +    delete view;
 +}
 +
 +void tst_qquickanchors::centerIn()
 +{
 +    QQuickView *view = new QQuickView(testFileUrl("centerin.qml"));
 +
 +    qApp->processEvents();
 +    QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
 +    QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
 +
++    QCOMPARE(rectPrivate->anchors()->horizontalCenterOffset(), 10.0);
++    QCOMPARE(rectPrivate->anchors()->verticalCenterOffset(), 30.0);
 +    QCOMPARE(rect->x(), 75.0 + 10);
 +    QCOMPARE(rect->y(), 75.0 + 30);
 +    //Alter Offsets (tests QTBUG-6631)
 +    rectPrivate->anchors()->setHorizontalCenterOffset(-20.0);
 +    rectPrivate->anchors()->setVerticalCenterOffset(-10.0);
++    QCOMPARE(rectPrivate->anchors()->horizontalCenterOffset(), -20.0);
++    QCOMPARE(rectPrivate->anchors()->verticalCenterOffset(), -10.0);
 +    QCOMPARE(rect->x(), 75.0 - 20.0);
 +    QCOMPARE(rect->y(), 75.0 - 10.0);
 +
 +    //QTBUG-21730 (use actual center to prevent animation jitter)
 +    QQuickRectangle* rect2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered2"));
 +    QCOMPARE(rect2->x(), 94.5);
 +    QCOMPARE(rect2->y(), 94.5);
 +
 +    delete view;
 +}
 +
 +void tst_qquickanchors::centerInRTL()
 +{
 +    QQuickView *view = new QQuickView(testFileUrl("centerin.qml"));
 +
 +    qApp->processEvents();
 +    QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
 +    QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
 +    mirrorAnchors(rect);
 +
 +    QCOMPARE(rect->x(), 75.0 - 10);
 +    QCOMPARE(rect->y(), 75.0 + 30);
 +    //Alter Offsets (tests QTBUG-6631)
 +    rectPrivate->anchors()->setHorizontalCenterOffset(-20.0);
 +    rectPrivate->anchors()->setVerticalCenterOffset(-10.0);
 +    QCOMPARE(rect->x(), 75.0 + 20.0);
 +    QCOMPARE(rect->y(), 75.0 - 10.0);
 +
 +    delete view;
 +}
 +
 +//QTBUG-12441
 +void tst_qquickanchors::centerInRotation()
 +{
 +    QQuickView *view = new QQuickView(testFileUrl("centerinRotation.qml"));
 +
 +    qApp->processEvents();
 +    QQuickRectangle* outer = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("outer"));
 +    QQuickRectangle* inner = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("inner"));
 +
 +    QCOMPARE(outer->x(), qreal(49.5));
 +    QCOMPARE(outer->y(), qreal(49.5));
 +    QCOMPARE(inner->x(), qreal(25.5));
 +    QCOMPARE(inner->y(), qreal(25.5));
 +
 +    delete view;
 +}
 +
 +void tst_qquickanchors::hvCenter()
 +{
 +    QQuickView *view = new QQuickView(testFileUrl("hvCenter.qml"));
 +
 +    qApp->processEvents();
 +    QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
 +    QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
 +
 +    // test QTBUG-10999
 +    QCOMPARE(rect->x(), 10.0);
 +    QCOMPARE(rect->y(), 19.0);
 +
 +    rectPrivate->anchors()->setHorizontalCenterOffset(-5.0);
 +    rectPrivate->anchors()->setVerticalCenterOffset(5.0);
 +    QCOMPARE(rect->x(), 10.0 - 5.0);
 +    QCOMPARE(rect->y(), 19.0 + 5.0);
 +
 +    delete view;
 +}
 +
 +void tst_qquickanchors::hvCenterRTL()
 +{
 +    QQuickView *view = new QQuickView(testFileUrl("hvCenter.qml"));
 +
 +    qApp->processEvents();
 +    QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("centered"));
 +    QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
 +    mirrorAnchors(rect);
 +
 +    // test QTBUG-10999
 +    QCOMPARE(rect->x(), 10.0);
 +    QCOMPARE(rect->y(), 19.0);
 +
 +    rectPrivate->anchors()->setHorizontalCenterOffset(-5.0);
 +    rectPrivate->anchors()->setVerticalCenterOffset(5.0);
 +    QCOMPARE(rect->x(), 10.0 + 5.0);
 +    QCOMPARE(rect->y(), 19.0 + 5.0);
 +
 +    delete view;
 +}
 +void tst_qquickanchors::margins()
 +{
 +    QQuickView *view = new QQuickView(testFileUrl("margins.qml"));
 +
 +    qApp->processEvents();
 +    QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
 +    QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
++    QCOMPARE(rectPrivate->anchors()->margins(), 10.0);
++    QCOMPARE(rectPrivate->anchors()->topMargin(), 6.0);
++    QCOMPARE(rectPrivate->anchors()->leftMargin(), 5.0);
++    QCOMPARE(rectPrivate->anchors()->bottomMargin(), 10.0);
++    QCOMPARE(rectPrivate->anchors()->rightMargin(), 10.0);
 +    QCOMPARE(rect->x(), 5.0);
 +    QCOMPARE(rect->y(), 6.0);
 +    QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
 +    QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
 +
 +    rectPrivate->anchors()->setTopMargin(0.0);
 +    rectPrivate->anchors()->setMargins(20.0);
 +
++    QCOMPARE(rectPrivate->anchors()->margins(), 20.0);
++    QEXPECT_FAIL("","QTBUG-24515", Continue);
++    QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0);
++    QCOMPARE(rectPrivate->anchors()->leftMargin(), 5.0);
++    QCOMPARE(rectPrivate->anchors()->bottomMargin(), 20.0);
++    QCOMPARE(rectPrivate->anchors()->rightMargin(), 20.0);
 +    QCOMPARE(rect->x(), 5.0);
 +    QCOMPARE(rect->y(), 20.0);
 +    QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
 +    QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0);
 +
 +    delete view;
 +}
 +
 +void tst_qquickanchors::marginsRTL()
 +{
 +    QQuickView *view = new QQuickView(testFileUrl("margins.qml"));
 +
 +    QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("filler"));
 +    QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
 +    mirrorAnchors(rect);
 +
 +    QCOMPARE(rect->x(), 10.0);
 +    QCOMPARE(rect->y(), 6.0);
 +    QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
 +    QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
 +
 +    rectPrivate->anchors()->setTopMargin(0.0);
 +    rectPrivate->anchors()->setMargins(20.0);
 +
 +    QCOMPARE(rect->x(), 20.0);
 +    QCOMPARE(rect->y(), 20.0);
 +    QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
 +    QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0);
 +
 +    delete view;
 +}
 +
++void tst_qquickanchors::stretch()
++{
++    QQuickView *view = new QQuickView(testFileUrl("stretch.qml"));
++
++    qApp->processEvents();
++    QQuickRectangle* rect = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("stretcher"));
++    QCOMPARE(rect->x(), 160.0);
++    QCOMPARE(rect->y(), 130.0);
++    QCOMPARE(rect->width(), 40.0);
++    QCOMPARE(rect->height(), 100.0);
++
++    QQuickRectangle* rect2 = findItem<QQuickRectangle>(view->rootObject(), QLatin1String("stretcher2"));
++    QCOMPARE(rect2->y(), 130.0);
++    QCOMPARE(rect2->height(), 100.0);
++
++    delete view;
++}
 +
 +QTEST_MAIN(tst_qquickanchors)
 +
 +#include "tst_qquickanchors.moc"
index 0000000,f9a5d5f..f9a5d5f
mode 000000,100644..100644
Binary files differ
index 0000000,0000000..3c20cce
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,15 @@@
++CONFIG += testcase
++TARGET = tst_qquickanimatedsprite
++SOURCES += tst_qquickanimatedsprite.cpp
++
++include (../../shared/util.pri)
++
++macx:CONFIG -= app_bundle
++
++testDataFiles.files = data
++testDataFiles.path = .
++DEPLOYMENT += testDataFiles
++
++CONFIG += parallel_test
++
++QT += core-private gui-private qml-private quick-private network testlib
index 0000000,0000000..37625cf
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,83 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the test suite of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++#include <QtTest/QtTest>
++#include "../../shared/util.h"
++#include <QtQuick/qquickview.h>
++#include <private/qquickanimatedsprite_p.h>
++
++class tst_qquickanimatedsprite : public QQmlDataTest
++{
++    Q_OBJECT
++public:
++    tst_qquickanimatedsprite(){}
++
++private slots:
++    void test_properties();
++};
++
++void tst_qquickanimatedsprite::test_properties()
++{
++    QQuickView *canvas = new QQuickView(0);
++
++    canvas->setSource(testFileUrl("basic.qml"));
++    canvas->show();
++    QTest::qWaitForWindowShown(canvas);
++
++    QVERIFY(canvas->rootObject());
++    QQuickAnimatedSprite* sprite = canvas->rootObject()->findChild<QQuickAnimatedSprite*>("sprite");
++    QVERIFY(sprite);
++
++    QVERIFY(sprite->running());
++    QVERIFY(!sprite->paused());
++    QVERIFY(sprite->interpolate());
++    QCOMPARE(sprite->loops(), 3);
++
++    sprite->setRunning(false);
++    QVERIFY(!sprite->running());
++    sprite->setInterpolate(false);
++    QVERIFY(!sprite->interpolate());
++
++    delete canvas;
++}
++
++QTEST_MAIN(tst_qquickanimatedsprite)
++
++#include "tst_qquickanimatedsprite.moc"
index 108bce6,0000000..dd01099
mode 100644,000000..100644
--- /dev/null
@@@ -1,1319 -1,0 +1,1334 @@@
- #include <QtQuick/private/qquickanimation_p.h>
- #include <QtQuick/private/qquicktransition_p.h>
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <QtTest/QtTest>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtQuick/qquickview.h>
 +#include <QtQml/private/qanimationgroupjob_p.h>
 +#include <QtQuick/private/qquickrectangle_p.h>
 +#include <QtQuick/private/qquickitemanimation_p.h>
++#include <QtQuick/private/qquickitemanimation_p_p.h>
++#include <QtQuick/private/qquicktransition_p.h>
++#include <QtQuick/private/qquickanimation_p.h>
 +#include <QtQuick/private/qquickpathinterpolator_p.h>
 +#include <QtQuick/private/qquickitem_p.h>
 +#include <QEasingCurve>
 +
 +#include <limits.h>
 +#include <math.h>
 +
 +#include "../../shared/util.h"
 +
 +class tst_qquickanimations : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_qquickanimations() {}
 +
 +private slots:
 +    void initTestCase()
 +    {
 +        QQmlEngine engine;  // ensure types are registered
 +        QQmlDataTest::initTestCase();
 +    }
 +
 +    void simpleProperty();
 +    void simpleNumber();
 +    void simpleColor();
 +    void simpleRotation();
 +    void simplePath();
 +    void simpleAnchor();
 +    void reparent();
 +    void pathInterpolator();
 +    void pathInterpolatorBackwardJump();
 +    void pathWithNoStart();
 +    void alwaysRunToEnd();
 +    void complete();
 +    void resume();
 +    void dotProperty();
 +    void badTypes();
 +    void badProperties();
 +    void mixedTypes();
 +    void properties();
 +    void propertiesTransition();
 +    void pathTransition();
 +    void disabledTransition();
 +    void invalidDuration();
 +    void attached();
 +    void propertyValueSourceDefaultStart();
 +    void dontStart();
 +    void easingProperties();
 +    void rotation();
 +    void runningTrueBug();
 +    void nonTransitionBug();
 +    void registrationBug();
 +    void doubleRegistrationBug();
 +    void alwaysRunToEndRestartBug();
 +    void transitionAssignmentBug();
 +    void pauseBindingBug();
 +    void pauseBug();
 +    void loopingBug();
++    void anchorBug();
 +};
 +
 +#define QTIMED_COMPARE(lhs, rhs) do { \
 +    for (int ii = 0; ii < 5; ++ii) { \
 +        if (lhs == rhs)  \
 +            break; \
 +        QTest::qWait(50); \
 +    } \
 +    QCOMPARE(lhs, rhs); \
 +} while (false)
 +
 +void tst_qquickanimations::simpleProperty()
 +{
 +    QQuickRectangle rect;
 +    QQuickPropertyAnimation animation;
 +    animation.setTargetObject(&rect);
 +    animation.setProperty("x");
 +    animation.setTo(200);
 +    QVERIFY(animation.target() == &rect);
 +    QVERIFY(animation.property() == "x");
 +    QVERIFY(animation.to().toReal() == 200.0);
 +    animation.start();
 +    QVERIFY(animation.isRunning());
 +    QTest::qWait(animation.duration());
 +    QTIMED_COMPARE(rect.x(), 200.0);
 +
 +    rect.setPos(QPointF(0,0));
 +    animation.start();
 +    QVERIFY(animation.isRunning());
 +    animation.pause();
 +    QVERIFY(animation.isPaused());
 +    animation.setCurrentTime(125);
 +    QVERIFY(animation.currentTime() == 125);
 +    QCOMPARE(rect.x(),100.0);
 +}
 +
 +void tst_qquickanimations::simpleNumber()
 +{
 +    QQuickRectangle rect;
 +    QQuickNumberAnimation animation;
 +    animation.setTargetObject(&rect);
 +    animation.setProperty("x");
 +    animation.setTo(200);
 +    QVERIFY(animation.target() == &rect);
 +    QVERIFY(animation.property() == "x");
 +    QVERIFY(animation.to() == 200);
 +    animation.start();
 +    QVERIFY(animation.isRunning());
 +    QTest::qWait(animation.duration());
 +    QTIMED_COMPARE(rect.x(), qreal(200));
 +
 +    rect.setX(0);
 +    animation.start();
 +    animation.pause();
 +    QVERIFY(animation.isRunning());
 +    QVERIFY(animation.isPaused());
 +    animation.setCurrentTime(125);
 +    QVERIFY(animation.currentTime() == 125);
 +    QCOMPARE(rect.x(), qreal(100));
 +}
 +
 +void tst_qquickanimations::simpleColor()
 +{
 +    QQuickRectangle rect;
 +    QQuickColorAnimation animation;
 +    animation.setTargetObject(&rect);
 +    animation.setProperty("color");
 +    animation.setTo(QColor("red"));
 +    QVERIFY(animation.target() == &rect);
 +    QVERIFY(animation.property() == "color");
 +    QVERIFY(animation.to() == QColor("red"));
 +    animation.start();
 +    QVERIFY(animation.isRunning());
 +    QTest::qWait(animation.duration());
 +    QTIMED_COMPARE(rect.color(), QColor("red"));
 +
 +    rect.setColor(QColor("blue"));
 +    animation.start();
 +    animation.pause();
 +    QVERIFY(animation.isRunning());
 +    QVERIFY(animation.isPaused());
 +    animation.setCurrentTime(125);
 +    QVERIFY(animation.currentTime() == 125);
 +#if defined(UBUNTU_ONEIRIC) && defined(__x86_64__)
 +    QEXPECT_FAIL("", "Fails on this platform - QTBUG-23385", Abort);
 +#endif
 +    QCOMPARE(rect.color(), QColor::fromRgbF(0.498039, 0, 0.498039, 1));
 +
 +    rect.setColor(QColor("green"));
 +    animation.setFrom(QColor("blue"));
 +    QVERIFY(animation.from() == QColor("blue"));
 +    animation.restart();
 +    QCOMPARE(rect.color(), QColor("blue"));
 +    QVERIFY(animation.isRunning());
 +    animation.setCurrentTime(125);
 +    QCOMPARE(rect.color(), QColor::fromRgbF(0.498039, 0, 0.498039, 1));
 +}
 +
 +void tst_qquickanimations::simpleRotation()
 +{
 +    QQuickRectangle rect;
 +    QQuickRotationAnimation animation;
 +    animation.setTargetObject(&rect);
 +    animation.setProperty("rotation");
 +    animation.setTo(270);
 +    QVERIFY(animation.target() == &rect);
 +    QVERIFY(animation.property() == "rotation");
 +    QVERIFY(animation.to() == 270);
 +    QVERIFY(animation.direction() == QQuickRotationAnimation::Numerical);
 +    animation.start();
 +    QVERIFY(animation.isRunning());
 +    QTest::qWait(animation.duration());
 +    QTIMED_COMPARE(rect.rotation(), qreal(270));
 +
 +    rect.setRotation(0);
 +    animation.start();
 +    animation.pause();
 +    QVERIFY(animation.isRunning());
 +    QVERIFY(animation.isPaused());
 +    animation.setCurrentTime(125);
 +    QVERIFY(animation.currentTime() == 125);
 +    QCOMPARE(rect.rotation(), qreal(135));
 +}
 +
 +void tst_qquickanimations::simplePath()
 +{
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("pathAnimation.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
 +        QVERIFY(redRect);
 +        QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>();
 +        QVERIFY(pathAnim);
 +
 +        QCOMPARE(pathAnim->duration(), 100);
 +        QCOMPARE(pathAnim->target(), redRect);
 +
 +        pathAnim->start();
 +        pathAnim->pause();
 +
 +        pathAnim->setCurrentTime(30);
 +        QCOMPARE(redRect->x(), qreal(167));
 +        QCOMPARE(redRect->y(), qreal(104));
 +
 +        pathAnim->setCurrentTime(100);
 +        QCOMPARE(redRect->x(), qreal(300));
 +        QCOMPARE(redRect->y(), qreal(300));
 +
 +        //verify animation runs to end
 +        pathAnim->start();
 +        QCOMPARE(redRect->x(), qreal(50));
 +        QCOMPARE(redRect->y(), qreal(50));
 +        QTRY_COMPARE(redRect->x(), qreal(300));
 +        QCOMPARE(redRect->y(), qreal(300));
 +
 +        pathAnim->setOrientation(QQuickPathAnimation::RightFirst);
 +        QCOMPARE(pathAnim->orientation(), QQuickPathAnimation::RightFirst);
 +        pathAnim->start();
 +        QTRY_VERIFY(redRect->rotation() != 0);
 +        pathAnim->stop();
 +
 +        delete rect;
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("pathAnimation2.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
 +        QVERIFY(redRect);
 +        QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>();
 +        QVERIFY(pathAnim);
 +
 +        QCOMPARE(pathAnim->orientation(), QQuickPathAnimation::RightFirst);
 +        QCOMPARE(pathAnim->endRotation(), qreal(0));
 +        QCOMPARE(pathAnim->orientationEntryDuration(), 10);
 +        QCOMPARE(pathAnim->orientationExitDuration(), 10);
 +
 +        pathAnim->start();
 +        pathAnim->pause();
 +        QCOMPARE(redRect->x(), qreal(50));
 +        QCOMPARE(redRect->y(), qreal(50));
 +        QCOMPARE(redRect->rotation(), qreal(-360));
 +
 +        pathAnim->setCurrentTime(50);
 +        QCOMPARE(redRect->x(), qreal(175));
 +        QCOMPARE(redRect->y(), qreal(175));
 +        QCOMPARE(redRect->rotation(), qreal(-315));
 +
 +        pathAnim->setCurrentTime(100);
 +        QCOMPARE(redRect->x(), qreal(300));
 +        QCOMPARE(redRect->y(), qreal(300));
 +        QCOMPARE(redRect->rotation(), qreal(0));
 +
 +        delete rect;
 +    }
 +}
 +
 +void tst_qquickanimations::simpleAnchor()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent c(&engine, testFileUrl("reanchor.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect);
 +
 +    QQuickRectangle *greenRect = rect->findChild<QQuickRectangle*>();
 +    QVERIFY(greenRect);
 +
 +    QCOMPARE(rect->state(), QLatin1String("reanchored"));
 +    QCOMPARE(greenRect->x(), qreal(10));
 +    QCOMPARE(greenRect->y(), qreal(0));
 +    QCOMPARE(greenRect->width(), qreal(190));
 +    QCOMPARE(greenRect->height(), qreal(150));
 +
 +    rect->setState("");
 +
 +    //verify animation in progress
 +    QTRY_VERIFY(greenRect->x() < 10 && greenRect->x() > 0);
 +    QVERIFY(greenRect->y() > 0 && greenRect->y() < 10);
 +    QVERIFY(greenRect->width() < 190 && greenRect->width() > 150);
 +    QVERIFY(greenRect->height() > 150 && greenRect->height() < 190);
 +
 +    //verify end state ("")
 +    QTRY_COMPARE(greenRect->x(), qreal(0));
 +    QCOMPARE(greenRect->y(), qreal(10));
 +    QCOMPARE(greenRect->width(), qreal(150));
 +    QCOMPARE(greenRect->height(), qreal(190));
 +
 +    rect->setState("reanchored2");
 +
 +    //verify animation in progress
 +    QTRY_VERIFY(greenRect->y() > 10 && greenRect->y() < 50);
 +    QVERIFY(greenRect->height() > 125 && greenRect->height() < 190);
 +    //NOTE: setting left/right anchors to undefined removes the anchors, but does not resize.
 +    QCOMPARE(greenRect->x(), qreal(0));
 +    QCOMPARE(greenRect->width(), qreal(150));
 +
 +    //verify end state ("reanchored2")
 +    QTRY_COMPARE(greenRect->y(), qreal(50));
 +    QCOMPARE(greenRect->height(), qreal(125));
 +    QCOMPARE(greenRect->x(), qreal(0));
 +    QCOMPARE(greenRect->width(), qreal(150));
 +
 +    rect->setState("reanchored");
 +
 +    //verify animation in progress
 +    QTRY_VERIFY(greenRect->x() < 10 && greenRect->x() > 0);
 +    QVERIFY(greenRect->y() > 0 && greenRect->y() < 50);
 +    QVERIFY(greenRect->width() < 190 && greenRect->width() > 150);
 +    QVERIFY(greenRect->height() > 125 && greenRect->height() < 150);
 +
 +    //verify end state ("reanchored")
 +    QTRY_COMPARE(greenRect->x(), qreal(10));
 +    QCOMPARE(greenRect->y(), qreal(0));
 +    QCOMPARE(greenRect->width(), qreal(190));
 +    QCOMPARE(greenRect->height(), qreal(150));
 +
 +    rect->setState("reanchored2");
 +
 +    //verify animation in progress
 +    QTRY_VERIFY(greenRect->x() < 10 && greenRect->x() > 0);
 +    QVERIFY(greenRect->y() > 0 && greenRect->y() < 50);
 +    QVERIFY(greenRect->width() < 190 && greenRect->width() > 150);
 +    QVERIFY(greenRect->height() > 125 && greenRect->height() < 150);
 +
 +    //verify end state ("reanchored2")
 +    QTRY_COMPARE(greenRect->x(), qreal(0));
 +    QCOMPARE(greenRect->y(), qreal(50));
 +    QCOMPARE(greenRect->width(), qreal(150));
 +    QCOMPARE(greenRect->height(), qreal(125));
 +
 +    delete rect;
 +}
 +
 +void tst_qquickanimations::reparent()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent c(&engine, testFileUrl("reparent.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect);
 +
 +    QQuickRectangle *target = rect->findChild<QQuickRectangle*>("target");
 +    QVERIFY(target);
 +
 +    QCOMPARE(target->parentItem(), rect);
 +    QCOMPARE(target->x(), qreal(0));
 +    QCOMPARE(target->y(), qreal(0));
 +    QCOMPARE(target->width(), qreal(50));
 +    QCOMPARE(target->height(), qreal(50));
 +    QCOMPARE(target->rotation(), qreal(0));
 +    QCOMPARE(target->scale(), qreal(1));
 +
 +    rect->setState("state1");
 +
 +    QQuickRectangle *viaParent = rect->findChild<QQuickRectangle*>("viaParent");
 +    QVERIFY(viaParent);
 +
 +    QQuickRectangle *newParent = rect->findChild<QQuickRectangle*>("newParent");
 +    QVERIFY(newParent);
 +
 +    QTest::qWait(100);
 +
 +    //animation in progress
 +    QTRY_COMPARE(target->parentItem(), viaParent);
 +    QVERIFY(target->x() > -100 && target->x() < 50);
 +    QVERIFY(target->y() > -100 && target->y() < 50);
 +    QVERIFY(target->width() > 50 && target->width() < 100);
 +    QCOMPARE(target->height(), qreal(50));
 +    QCOMPARE(target->rotation(), qreal(-45));
 +    QCOMPARE(target->scale(), qreal(.5));
 +
 +    //end state
 +    QTRY_COMPARE(target->parentItem(), newParent);
 +    QCOMPARE(target->x(), qreal(50));
 +    QCOMPARE(target->y(), qreal(50));
 +    QCOMPARE(target->width(), qreal(100));
 +    QCOMPARE(target->height(), qreal(50));
 +    QCOMPARE(target->rotation(), qreal(0));
 +    QCOMPARE(target->scale(), qreal(1));
 +
 +    delete rect;
 +}
 +
 +void tst_qquickanimations::pathInterpolator()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent c(&engine, testFileUrl("pathInterpolator.qml"));
 +    QQuickPathInterpolator *interpolator = qobject_cast<QQuickPathInterpolator*>(c.create());
 +    QVERIFY(interpolator);
 +
 +    QCOMPARE(interpolator->progress(), qreal(0));
 +    QCOMPARE(interpolator->x(), qreal(50));
 +    QCOMPARE(interpolator->y(), qreal(50));
 +    QCOMPARE(interpolator->angle(), qreal(0));
 +
 +    interpolator->setProgress(.5);
 +    QCOMPARE(interpolator->progress(), qreal(.5));
 +    QCOMPARE(interpolator->x(), qreal(175));
 +    QCOMPARE(interpolator->y(), qreal(175));
 +    QCOMPARE(interpolator->angle(), qreal(90));
 +
 +    interpolator->setProgress(1);
 +    QCOMPARE(interpolator->progress(), qreal(1));
 +    QCOMPARE(interpolator->x(), qreal(300));
 +    QCOMPARE(interpolator->y(), qreal(300));
 +    QCOMPARE(interpolator->angle(), qreal(0));
 +}
 +
 +void tst_qquickanimations::pathInterpolatorBackwardJump()
 +{
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("pathInterpolatorBack.qml"));
 +        QQuickPathInterpolator *interpolator = qobject_cast<QQuickPathInterpolator*>(c.create());
 +        QVERIFY(interpolator);
 +
 +        QCOMPARE(interpolator->progress(), qreal(0));
 +        QCOMPARE(interpolator->x(), qreal(50));
 +        QCOMPARE(interpolator->y(), qreal(50));
 +        QCOMPARE(interpolator->angle(), qreal(90));
 +
 +        interpolator->setProgress(.5);
 +        QCOMPARE(interpolator->progress(), qreal(.5));
 +        QCOMPARE(interpolator->x(), qreal(100));
 +        QCOMPARE(interpolator->y(), qreal(75));
 +        QCOMPARE(interpolator->angle(), qreal(270));
 +
 +        interpolator->setProgress(1);
 +        QCOMPARE(interpolator->progress(), qreal(1));
 +        QCOMPARE(interpolator->x(), qreal(200));
 +        QCOMPARE(interpolator->y(), qreal(50));
 +        QCOMPARE(interpolator->angle(), qreal(0));
 +
 +        //make sure we don't get caught in infinite loop here
 +        interpolator->setProgress(0);
 +        QCOMPARE(interpolator->progress(), qreal(0));
 +        QCOMPARE(interpolator->x(), qreal(50));
 +        QCOMPARE(interpolator->y(), qreal(50));
 +        QCOMPARE(interpolator->angle(), qreal(90));
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("pathInterpolatorBack2.qml"));
 +        QQuickPathInterpolator *interpolator = qobject_cast<QQuickPathInterpolator*>(c.create());
 +        QVERIFY(interpolator);
 +
 +        QCOMPARE(interpolator->progress(), qreal(0));
 +        QCOMPARE(interpolator->x(), qreal(200));
 +        QCOMPARE(interpolator->y(), qreal(280));
 +        QCOMPARE(interpolator->angle(), qreal(180));
 +
 +        interpolator->setProgress(1);
 +        QCOMPARE(interpolator->progress(), qreal(1));
 +        QCOMPARE(interpolator->x(), qreal(0));
 +        QCOMPARE(interpolator->y(), qreal(80));
 +        QCOMPARE(interpolator->angle(), qreal(180));
 +
 +        //make sure we don't get caught in infinite loop here
 +        interpolator->setProgress(0);
 +        QCOMPARE(interpolator->progress(), qreal(0));
 +        QCOMPARE(interpolator->x(), qreal(200));
 +        QCOMPARE(interpolator->y(), qreal(280));
 +        QCOMPARE(interpolator->angle(), qreal(180));
 +    }
 +}
 +
 +void tst_qquickanimations::pathWithNoStart()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent c(&engine, testFileUrl("pathAnimationNoStart.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect);
 +
 +    QQuickRectangle *redRect = rect->findChild<QQuickRectangle*>();
 +    QVERIFY(redRect);
 +    QQuickPathAnimation *pathAnim = rect->findChild<QQuickPathAnimation*>();
 +    QVERIFY(pathAnim);
 +
 +    pathAnim->start();
 +    pathAnim->pause();
 +    QCOMPARE(redRect->x(), qreal(50));
 +    QCOMPARE(redRect->y(), qreal(50));
 +
 +    pathAnim->setCurrentTime(50);
 +    QCOMPARE(redRect->x(), qreal(175));
 +    QCOMPARE(redRect->y(), qreal(175));
 +
 +    pathAnim->setCurrentTime(100);
 +    QCOMPARE(redRect->x(), qreal(300));
 +    QCOMPARE(redRect->y(), qreal(300));
 +
 +    redRect->setX(100);
 +    redRect->setY(100);
 +    pathAnim->start();
 +    QCOMPARE(redRect->x(), qreal(100));
 +    QCOMPARE(redRect->y(), qreal(100));
 +    QTRY_COMPARE(redRect->x(), qreal(300));
 +    QCOMPARE(redRect->y(), qreal(300));
 +}
 +
 +void tst_qquickanimations::alwaysRunToEnd()
 +{
 +    QQuickRectangle rect;
 +    QQuickPropertyAnimation animation;
 +    animation.setTargetObject(&rect);
 +    animation.setProperty("x");
 +    animation.setTo(200);
 +    animation.setDuration(1000);
 +    animation.setLoops(-1);
 +    animation.setAlwaysRunToEnd(true);
 +    QVERIFY(animation.loops() == -1);
 +    QVERIFY(animation.alwaysRunToEnd() == true);
 +    animation.start();
 +    QTest::qWait(1500);
 +    animation.stop();
 +    QVERIFY(rect.x() != qreal(200));
 +    QTest::qWait(500);
 +    QTIMED_COMPARE(rect.x(), qreal(200));
 +}
 +
 +void tst_qquickanimations::complete()
 +{
 +    QQuickRectangle rect;
 +    QQuickPropertyAnimation animation;
 +    animation.setTargetObject(&rect);
 +    animation.setProperty("x");
 +    animation.setFrom(1);
 +    animation.setTo(200);
 +    animation.setDuration(500);
 +    QVERIFY(animation.from() == 1);
 +    animation.start();
 +    QTest::qWait(50);
 +    animation.stop();
 +    QVERIFY(rect.x() != qreal(200));
 +    animation.start();
 +    QTest::qWait(50);
 +    QVERIFY(animation.isRunning());
 +    animation.complete();
 +    QCOMPARE(rect.x(), qreal(200));
 +}
 +
 +void tst_qquickanimations::resume()
 +{
 +    QQuickRectangle rect;
 +    QQuickPropertyAnimation animation;
 +    animation.setTargetObject(&rect);
 +    animation.setProperty("x");
 +    animation.setFrom(10);
 +    animation.setTo(200);
 +    animation.setDuration(1000);
 +    QVERIFY(animation.from() == 10);
 +
 +    animation.start();
 +    QTest::qWait(400);
 +    animation.pause();
 +    qreal x = rect.x();
 +    QVERIFY(x != qreal(200) && x != qreal(10));
 +    QVERIFY(animation.isRunning());
 +    QVERIFY(animation.isPaused());
 +
 +    animation.resume();
 +    QVERIFY(animation.isRunning());
 +    QVERIFY(!animation.isPaused());
 +    QTest::qWait(400);
 +    animation.stop();
 +    QVERIFY(rect.x() > x);
 +}
 +
 +void tst_qquickanimations::dotProperty()
 +{
 +    QQuickRectangle rect;
 +    QQuickNumberAnimation animation;
 +    animation.setTargetObject(&rect);
 +    animation.setProperty("border.width");
 +    animation.setTo(10);
 +    animation.start();
 +    QTest::qWait(animation.duration()+50);
 +    QTIMED_COMPARE(rect.border()->width(), 10.0);
 +
 +    rect.border()->setWidth(0);
 +    animation.start();
 +    animation.pause();
 +    animation.setCurrentTime(125);
 +    QVERIFY(animation.currentTime() == 125);
 +    QCOMPARE(rect.border()->width(), 5.0);
 +}
 +
 +void tst_qquickanimations::badTypes()
 +{
 +    //don't crash
 +    {
 +        QQuickView *view = new QQuickView;
 +        view->setSource(testFileUrl("badtype1.qml"));
 +
 +        qApp->processEvents();
 +
 +        delete view;
 +    }
 +
 +    //make sure we get a compiler error
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("badtype2.qml"));
 +        QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
 +        c.create();
 +
 +        QVERIFY(c.errors().count() == 1);
 +        QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: number expected"));
 +    }
 +
 +    //make sure we get a compiler error
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("badtype3.qml"));
 +        QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
 +        c.create();
 +
 +        QVERIFY(c.errors().count() == 1);
 +        QCOMPARE(c.errors().at(0).description(), QLatin1String("Invalid property assignment: color expected"));
 +    }
 +
 +    //don't crash
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("badtype4.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickItemPrivate::get(rect)->setState("state1");
 +        QTest::qWait(1000 + 50);
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
 +        QVERIFY(myRect);
 +        QCOMPARE(myRect->x(),qreal(200));
 +    }
 +}
 +
 +void tst_qquickanimations::badProperties()
 +{
 +    //make sure we get a runtime error
 +    {
 +        QQmlEngine engine;
 +
 +        QQmlComponent c1(&engine, testFileUrl("badproperty1.qml"));
 +        QByteArray message = testFileUrl("badproperty1.qml").toString().toUtf8() + ":18:9: QML ColorAnimation: Cannot animate non-existent property \"border.colr\"";
 +        QTest::ignoreMessage(QtWarningMsg, message);
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c1.create());
 +        QVERIFY(rect);
 +
 +        QQmlComponent c2(&engine, testFileUrl("badproperty2.qml"));
 +        message = testFileUrl("badproperty2.qml").toString().toUtf8() + ":18:9: QML ColorAnimation: Cannot animate read-only property \"border\"";
 +        QTest::ignoreMessage(QtWarningMsg, message);
 +        rect = qobject_cast<QQuickRectangle*>(c2.create());
 +        QVERIFY(rect);
 +
 +        //### should we warn here are well?
 +        //rect->setState("state1");
 +    }
 +}
 +
 +//test animating mixed types with property animation in a transition
 +//for example, int + real; color + real; etc
 +void tst_qquickanimations::mixedTypes()
 +{
 +    //assumes border.width stays a real -- not real robust
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("mixedtype1.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickItemPrivate::get(rect)->setState("state1");
 +        QTest::qWait(500);
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
 +        QVERIFY(myRect);
 +
 +        //rather inexact -- is there a better way?
 +        QVERIFY(myRect->x() > 100 && myRect->x() < 200);
 +        QVERIFY(myRect->border()->width() > 1 && myRect->border()->width() < 10);
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("mixedtype2.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickItemPrivate::get(rect)->setState("state1");
 +        QTest::qWait(500);
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
 +        QVERIFY(myRect);
 +
 +        //rather inexact -- is there a better way?
 +        QVERIFY(myRect->x() > 100 && myRect->x() < 200);
 +#if defined(UBUNTU_ONEIRIC) && defined(__x86_64__)
 +        QEXPECT_FAIL("", "Fails on this platform - QTBUG-23385", Continue);
 +#endif
 +        QVERIFY(myRect->color() != QColor("red") && myRect->color() != QColor("blue"));
 +    }
 +}
 +
 +void tst_qquickanimations::properties()
 +{
 +    const int waitDuration = 300;
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("properties.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->x(),qreal(200));
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("properties2.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->x(),qreal(200));
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("properties3.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->x(),qreal(300));
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("properties4.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->y(),qreal(200));
 +        QTIMED_COMPARE(myRect->x(),qreal(100));
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("properties5.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->x(),qreal(100));
 +        QTIMED_COMPARE(myRect->y(),qreal(200));
 +    }
 +}
 +
 +void tst_qquickanimations::propertiesTransition()
 +{
 +    const int waitDuration = 300;
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("propertiesTransition.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickItemPrivate::get(rect)->setState("moved");
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->x(),qreal(200));
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("propertiesTransition2.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QQuickItemPrivate::get(rect)->setState("moved");
 +        QCOMPARE(myRect->x(),qreal(200));
 +        QCOMPARE(myRect->y(),qreal(100));
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->y(),qreal(200));
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("propertiesTransition3.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QQuickItemPrivate::get(rect)->setState("moved");
 +        QCOMPARE(myRect->x(),qreal(200));
 +        QCOMPARE(myRect->y(),qreal(100));
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("propertiesTransition4.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QQuickItemPrivate::get(rect)->setState("moved");
 +        QCOMPARE(myRect->x(),qreal(100));
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->x(),qreal(200));
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("propertiesTransition5.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QQuickItemPrivate::get(rect)->setState("moved");
 +        QCOMPARE(myRect->x(),qreal(100));
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->x(),qreal(200));
 +    }
 +
 +    /*{
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("propertiesTransition6.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QQuickItemPrivate::get(rect)->setState("moved");
 +        QCOMPARE(myRect->x(),qreal(100));
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->x(),qreal(100));
 +    }*/
 +
 +    {
 +        QQmlEngine engine;
 +        QQmlComponent c(&engine, testFileUrl("propertiesTransition7.qml"));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickItemPrivate::get(rect)->setState("moved");
 +        QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +        QVERIFY(myRect);
 +        QTest::qWait(waitDuration);
 +        QTIMED_COMPARE(myRect->x(),qreal(200));
 +    }
 +
 +}
 +
 +void tst_qquickanimations::pathTransition()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent c(&engine, testFileUrl("pathTransition.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect);
 +
 +    QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("redRect");
 +    QVERIFY(myRect);
 +
 +    QQuickItemPrivate::get(rect)->setState("moved");
 +    QTRY_VERIFY(myRect->x() < 500 && myRect->x() > 100 && myRect->y() > 50 && myRect->y() < 700 );  //animation started
 +    QTRY_VERIFY(qFuzzyCompare(myRect->x(), qreal(100)) && qFuzzyCompare(myRect->y(), qreal(700)));
 +    QTest::qWait(100);
 +
 +    QQuickItemPrivate::get(rect)->setState("");
 +    QTRY_VERIFY(myRect->x() < 500 && myRect->x() > 100 && myRect->y() > 50 && myRect->y() < 700 );  //animation started
 +    QTRY_VERIFY(qFuzzyCompare(myRect->x(), qreal(500)) && qFuzzyCompare(myRect->y(), qreal(50)));
 +}
 +
 +void tst_qquickanimations::disabledTransition()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent c(&engine, testFileUrl("disabledTransition.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect);
 +
 +    QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("TheRect");
 +    QVERIFY(myRect);
 +
 +    QQuickTransition *trans = rect->findChild<QQuickTransition*>();
 +    QVERIFY(trans);
 +
 +    QCOMPARE(trans->enabled(), false);
 +
 +    QQuickItemPrivate::get(rect)->setState("moved");
 +    QCOMPARE(myRect->x(),qreal(200));
 +
 +    trans->setEnabled(true);
 +
 +    QQuickItemPrivate::get(rect)->setState("");
 +    QCOMPARE(myRect->x(),qreal(200));
 +    QTest::qWait(300);
 +    QTIMED_COMPARE(myRect->x(),qreal(100));
 +}
 +
 +void tst_qquickanimations::invalidDuration()
 +{
 +    QQuickPropertyAnimation *animation = new QQuickPropertyAnimation;
 +    QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML PropertyAnimation: Cannot set a duration of < 0");
 +    animation->setDuration(-1);
 +    QCOMPARE(animation->duration(), 250);
 +
 +    QQuickPauseAnimation *pauseAnimation = new QQuickPauseAnimation;
 +    QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML PauseAnimation: Cannot set a duration of < 0");
 +    pauseAnimation->setDuration(-1);
 +    QCOMPARE(pauseAnimation->duration(), 250);
 +}
 +
 +void tst_qquickanimations::attached()
 +{
 +    QQmlEngine engine;
 +
 +    QQmlComponent c(&engine, testFileUrl("attached.qml"));
 +    QTest::ignoreMessage(QtDebugMsg, "off");
 +    QTest::ignoreMessage(QtDebugMsg, "on");
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect);
 +}
 +
 +void tst_qquickanimations::propertyValueSourceDefaultStart()
 +{
 +    {
 +        QQmlEngine engine;
 +
 +        QQmlComponent c(&engine, testFileUrl("valuesource.qml"));
 +
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
 +        QVERIFY(myAnim);
 +        QVERIFY(myAnim->isRunning());
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +
 +        QQmlComponent c(&engine, testFileUrl("valuesource2.qml"));
 +
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
 +        QVERIFY(myAnim);
 +        QVERIFY(myAnim->isRunning() == false);
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +
 +        QQmlComponent c(&engine, testFileUrl("dontAutoStart.qml"));
 +
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
 +        QVERIFY(myAnim && !myAnim->qtAnimation());
 +        //QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimationJob::Stopped);
 +    }
 +}
 +
 +
 +void tst_qquickanimations::dontStart()
 +{
 +    {
 +        QQmlEngine engine;
 +
 +        QQmlComponent c(&engine, testFileUrl("dontStart.qml"));
 +
 +        QString warning = c.url().toString() + ":14:13: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
 +        QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
 +        QVERIFY(myAnim && !myAnim->qtAnimation());
 +        //QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimationJob::Stopped);
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +
 +        QQmlComponent c(&engine, testFileUrl("dontStart2.qml"));
 +
 +        QString warning = c.url().toString() + ":15:17: QML NumberAnimation: setRunning() cannot be used on non-root animation nodes.";
 +        QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +        QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +        QVERIFY(rect);
 +
 +        QQuickAbstractAnimation *myAnim = rect->findChild<QQuickAbstractAnimation*>("MyAnim");
 +        QVERIFY(myAnim && !myAnim->qtAnimation());
 +        //QVERIFY(myAnim->qtAnimation()->state() == QAbstractAnimationJob::Stopped);
 +    }
 +}
 +
 +void tst_qquickanimations::easingProperties()
 +{
 +    {
 +        QQmlEngine engine;
 +        QString componentStr = "import QtQuick 2.0\nNumberAnimation { easing.type: \"InOutQuad\" }";
 +        QQmlComponent animationComponent(&engine);
 +        animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
 +
 +        QVERIFY(animObject != 0);
 +        QCOMPARE(animObject->easing().type(), QEasingCurve::InOutQuad);
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"OutBounce\"; easing.amplitude: 5.0 }";
 +        QQmlComponent animationComponent(&engine);
 +        animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
 +
 +        QVERIFY(animObject != 0);
 +        QCOMPARE(animObject->easing().type(), QEasingCurve::OutBounce);
 +        QCOMPARE(animObject->easing().amplitude(), 5.0);
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"OutElastic\"; easing.amplitude: 5.0; easing.period: 3.0}";
 +        QQmlComponent animationComponent(&engine);
 +        animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
 +
 +        QVERIFY(animObject != 0);
 +        QCOMPARE(animObject->easing().type(), QEasingCurve::OutElastic);
 +        QCOMPARE(animObject->easing().amplitude(), 5.0);
 +        QCOMPARE(animObject->easing().period(), 3.0);
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"InOutBack\"; easing.overshoot: 2 }";
 +        QQmlComponent animationComponent(&engine);
 +        animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
 +
 +        QVERIFY(animObject != 0);
 +        QCOMPARE(animObject->easing().type(), QEasingCurve::InOutBack);
 +        QCOMPARE(animObject->easing().overshoot(), 2.0);
 +    }
 +
 +    {
 +        QQmlEngine engine;
 +        QString componentStr = "import QtQuick 2.0\nPropertyAnimation { easing.type: \"Bezier\"; easing.bezierCurve: [0.5, 0.2, 0.13, 0.65, 1.0, 1.0] }";
 +        QQmlComponent animationComponent(&engine);
 +        animationComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickPropertyAnimation *animObject = qobject_cast<QQuickPropertyAnimation*>(animationComponent.create());
 +
 +        QVERIFY(animObject != 0);
 +        QCOMPARE(animObject->easing().type(), QEasingCurve::BezierSpline);
 +        QList<QPointF> points = animObject->easing().cubicBezierSpline();
 +        QCOMPARE(points.count(), 3);
 +        QCOMPARE(points.at(0), QPointF(0.5, 0.2));
 +        QCOMPARE(points.at(1), QPointF(0.13, 0.65));
 +        QCOMPARE(points.at(2), QPointF(1.0, 1.0));
 +    }
 +}
 +
 +void tst_qquickanimations::rotation()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent c(&engine, testFileUrl("rotation.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect);
 +
 +    QQuickRectangle *rr = rect->findChild<QQuickRectangle*>("rr");
 +    QQuickRectangle *rr2 = rect->findChild<QQuickRectangle*>("rr2");
 +    QQuickRectangle *rr3 = rect->findChild<QQuickRectangle*>("rr3");
 +    QQuickRectangle *rr4 = rect->findChild<QQuickRectangle*>("rr4");
 +
 +    QQuickItemPrivate::get(rect)->setState("state1");
 +    QTest::qWait(800);
 +    qreal r1 = rr->rotation();
 +    qreal r2 = rr2->rotation();
 +    qreal r3 = rr3->rotation();
 +    qreal r4 = rr4->rotation();
 +
 +    QVERIFY(r1 > qreal(0) && r1 < qreal(370));
 +    QVERIFY(r2 > qreal(0) && r2 < qreal(370));
 +    QVERIFY(r3 < qreal(0) && r3 > qreal(-350));
 +    QVERIFY(r4 > qreal(0) && r4 < qreal(10));
 +    QCOMPARE(r1,r2);
 +    QVERIFY(r4 < r2);
 +
 +    QTest::qWait(800);
 +    QTIMED_COMPARE(rr->rotation() + rr2->rotation() + rr3->rotation() + rr4->rotation(), qreal(370*4));
 +}
 +
 +void tst_qquickanimations::runningTrueBug()
 +{
 +    //ensure we start correctly when "running: true" is explicitly set
 +    QQmlEngine engine;
 +    QQmlComponent c(&engine, testFileUrl("runningTrueBug.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect);
 +
 +    QQuickRectangle *cloud = rect->findChild<QQuickRectangle*>("cloud");
 +    QVERIFY(cloud);
 +    QTest::qWait(1000);
 +    QVERIFY(cloud->x() > qreal(0));
 +}
 +
 +//QTBUG-12805
 +void tst_qquickanimations::nonTransitionBug()
 +{
 +    //tests that the animation values from the previous transition are properly cleared
 +    //in the case where an animation in the transition doesn't match anything (but previously did)
 +    QQmlEngine engine;
 +
 +    QQmlComponent c(&engine, testFileUrl("nonTransitionBug.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect != 0);
 +    QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
 +    QQuickRectangle *mover = rect->findChild<QQuickRectangle*>("mover");
 +
 +    mover->setX(100);
 +    QCOMPARE(mover->x(), qreal(100));
 +
 +    rectPrivate->setState("left");
 +    QTRY_COMPARE(mover->x(), qreal(0));
 +
 +    mover->setX(100);
 +    QCOMPARE(mover->x(), qreal(100));
 +
 +    //make sure we don't try to animate back to 0
 +    rectPrivate->setState("free");
 +    QTest::qWait(300);
 +    QCOMPARE(mover->x(), qreal(100));
 +}
 +
 +//QTBUG-14042
 +void tst_qquickanimations::registrationBug()
 +{
 +    QQmlEngine engine;
 +
 +    QQmlComponent c(&engine, testFileUrl("registrationBug.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect != 0);
 +    QTRY_COMPARE(rect->property("value"), QVariant(int(100)));
 +}
 +
 +void tst_qquickanimations::doubleRegistrationBug()
 +{
 +    QQmlEngine engine;
 +
 +    QQmlComponent c(&engine, testFileUrl("doubleRegistrationBug.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect != 0);
 +
 +    QQuickAbstractAnimation *anim = rect->findChild<QQuickAbstractAnimation*>("animation");
 +    QVERIFY(anim != 0);
 +    QTRY_COMPARE(anim->qtAnimation()->state(), QAbstractAnimationJob::Stopped);
 +}
 +
 +//QTBUG-16736
 +void tst_qquickanimations::alwaysRunToEndRestartBug()
 +{
 +    QQuickRectangle rect;
 +    QQuickPropertyAnimation animation;
 +    animation.setTargetObject(&rect);
 +    animation.setProperty("x");
 +    animation.setTo(200);
 +    animation.setDuration(1000);
 +    animation.setLoops(-1);
 +    animation.setAlwaysRunToEnd(true);
 +    QVERIFY(animation.loops() == -1);
 +    QVERIFY(animation.alwaysRunToEnd() == true);
 +    animation.start();
 +    animation.stop();
 +    animation.start();
 +    animation.stop();
 +    QTest::qWait(500);
 +    QVERIFY(rect.x() != qreal(200));
 +    QTest::qWait(800);
 +    QTIMED_COMPARE(rect.x(), qreal(200));
 +    QCOMPARE(static_cast<QQuickAbstractAnimation*>(&animation)->qtAnimation()->state(), QAbstractAnimationJob::Stopped);
 +}
 +
 +//QTBUG-20227
 +void tst_qquickanimations::transitionAssignmentBug()
 +{
 +    QQmlEngine engine;
 +
 +    QQmlComponent c(&engine, testFileUrl("transitionAssignmentBug.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect != 0);
 +
 +    QCOMPARE(rect->property("nullObject").toBool(), false);
 +}
 +
 +//QTBUG-19080
 +void tst_qquickanimations::pauseBindingBug()
 +{
 +    QQmlEngine engine;
 +
 +    QQmlComponent c(&engine, testFileUrl("pauseBindingBug.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
 +    QVERIFY(rect != 0);
 +    QQuickAbstractAnimation *anim = rect->findChild<QQuickAbstractAnimation*>("animation");
 +    QVERIFY(anim->qtAnimation()->state() == QAbstractAnimationJob::Paused);
 +
 +    delete rect;
 +}
 +
 +//QTBUG-13598
 +void tst_qquickanimations::pauseBug()
 +{
 +    QQmlEngine engine;
 +
 +    QQmlComponent c(&engine, testFileUrl("pauseBug.qml"));
 +    QQuickAbstractAnimation *anim = qobject_cast<QQuickAbstractAnimation*>(c.create());
 +    QVERIFY(anim != 0);
 +    QCOMPARE(anim->qtAnimation()->state(), QAbstractAnimationJob::Paused);
 +    QCOMPARE(anim->isPaused(), true);
 +    QCOMPARE(anim->isRunning(), true);
 +
 +    delete anim;
 +}
 +
 +//QTBUG-23092
 +void tst_qquickanimations::loopingBug()
 +{
 +    QQmlEngine engine;
 +
 +    QQmlComponent c(&engine, testFileUrl("looping.qml"));
 +    QObject *obj = c.create();
 +
 +    QQuickAbstractAnimation *anim = obj->findChild<QQuickAbstractAnimation*>();
 +    QVERIFY(anim != 0);
 +    QCOMPARE(anim->qtAnimation()->totalDuration(), 300);
 +    QCOMPARE(anim->isRunning(), true);
 +    QTRY_COMPARE(static_cast<QAnimationGroupJob*>(anim->qtAnimation())->firstChild()->currentLoop(), 2);
 +    QTRY_COMPARE(anim->isRunning(), false);
 +
 +    QQuickRectangle *rect = obj->findChild<QQuickRectangle*>();
 +    QVERIFY(rect != 0);
 +    QCOMPARE(rect->rotation(), qreal(90));
 +
 +    delete obj;
 +}
 +
++//QTBUG-24532
++void tst_qquickanimations::anchorBug()
++{
++    QQuickAnchorAnimation animation;
++    animation.setDuration(5000);
++    animation.setEasing(QEasingCurve(QEasingCurve::InOutBack));
++    animation.start();
++    animation.pause();
++
++    QCOMPARE(animation.qtAnimation()->duration(), 5000);
++    QCOMPARE(static_cast<QQuickBulkValueAnimator*>(animation.qtAnimation())->easingCurve(), QEasingCurve(QEasingCurve::InOutBack));
++}
++
 +QTEST_MAIN(tst_qquickanimations)
 +
 +#include "tst_qquickanimations.moc"
index 5ae8d22,0000000..41bcaac
mode 100644,000000..100644
--- /dev/null
@@@ -1,9 -1,0 +1,11 @@@
 +TARGET = tst_qquickdroparea
 +CONFIG += testcase
 +macx:CONFIG -= app_bundle
 +
 +SOURCES += tst_qquickdroparea.cpp
 +
 +CONFIG += parallel_test
 +
 +QT += core-private gui-private qml-private quick-private network testlib
++
++mac: CONFIG += insignificant_test # QTBUG-24588
index ed7a0aa,0000000..38fb02d
mode 100644,000000..100644
--- /dev/null
@@@ -1,1117 -1,0 +1,1118 @@@
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include <QtTest/QtTest>
 +#include <QtTest/QSignalSpy>
 +#include <QtQuick/qquickitem.h>
 +#include <QtQuick/qquickview.h>
 +#include <QtQml/qqmlcontext.h>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlexpression.h>
 +
 +#include <QtGui/qwindowsysteminterface_qpa.h>
++#include <QtGui/qplatformdrag_qpa.h>
 +
 +template <typename T> static T evaluate(QObject *scope, const QString &expression)
 +{
 +    QQmlExpression expr(qmlContext(scope), scope, expression);
 +    QVariant result = expr.evaluate();
 +    if (expr.hasError())
 +        qWarning() << expr.error().toString();
 +    return result.value<T>();
 +}
 +
 +template <> void evaluate<void>(QObject *scope, const QString &expression)
 +{
 +    QQmlExpression expr(qmlContext(scope), scope, expression);
 +    expr.evaluate();
 +    if (expr.hasError())
 +        qWarning() << expr.error().toString();
 +}
 +
 +class tst_QQuickDropArea: public QObject
 +{
 +    Q_OBJECT
 +private slots:
 +    void initTestCase();
 +    void cleanupTestCase();
 +
 +    void containsDrag_internal();
 +    void containsDrag_external();
 +    void keys_internal();
 +    void keys_external();
 +    void source_internal();
 +//    void source_external();
 +    void position_internal();
 +    void position_external();
 +    void drop_internal();
 +//    void drop_external();
 +    void simultaneousDrags();
 +
 +private:
 +    QQmlEngine engine;
 +};
 +
 +void tst_QQuickDropArea::initTestCase()
 +{
 +
 +}
 +
 +void tst_QQuickDropArea::cleanupTestCase()
 +{
 +
 +}
 +
 +void tst_QQuickDropArea::containsDrag_internal()
 +{
 +    QQuickCanvas canvas;
 +    QQmlComponent component(&engine);
 +    component.setData(
 +            "import QtQuick 2.0\n"
 +            "DropArea {\n"
 +                "property bool hasDrag: containsDrag\n"
 +                "property int enterEvents: 0\n"
 +                "property int exitEvents: 0\n"
 +                "width: 100; height: 100\n"
 +                "onEntered: {++enterEvents}\n"
 +                "onExited: {++exitEvents}\n"
 +                "Item {\n"
 +                    "objectName: \"dragItem\"\n"
 +                    "x: 50; y: 50\n"
 +                    "width: 10; height: 10\n"
 +                "}\n"
 +            "}", QUrl());
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
 +    QVERIFY(dropArea);
 +    dropArea->setParentItem(canvas.rootItem());
 +
 +    QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
 +    QVERIFY(dragItem);
 +
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
 +
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
 +
 +    evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
 +
 +    dragItem->setPos(QPointF(150, 50));
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
 +
 +    dragItem->setPos(QPointF(50, 50));
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
 +    dragItem->setPos(QPointF(150, 50));
 +
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +}
 +
 +void tst_QQuickDropArea::containsDrag_external()
 +{
 +    QQuickCanvas canvas;
 +    QQmlComponent component(&engine);
 +    component.setData(
 +            "import QtQuick 2.0\n"
 +            "DropArea {\n"
 +                "property bool hasDrag: containsDrag\n"
 +                "property int enterEvents: 0\n"
 +                "property int exitEvents: 0\n"
 +                "width: 100; height: 100\n"
 +                "onEntered: {++enterEvents}\n"
 +                "onExited: {++exitEvents}\n"
 +            "}", QUrl());
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
 +    QVERIFY(dropArea);
 +    dropArea->setParentItem(canvas.rootItem());
 +
 +    QMimeData data;
 +    QQuickCanvas alternateCanvas;
 +
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
 +
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(150, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
 +
 +    evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(150, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(150, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea, "{ enterEvents = 0; exitEvents = 0 }");
 +
-     QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(150, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(150, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<bool>(dropArea, "hasDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea, "exitEvents"), 1);
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(150, 50), Qt::CopyAction);
 +}
 +
 +void tst_QQuickDropArea::keys_internal()
 +{
 +    QQuickCanvas canvas;
 +    QQmlComponent component(&engine);
 +    component.setData(
 +            "import QtQuick 2.0\n"
 +            "DropArea {\n"
 +                "property variant dragKeys\n"
 +                "property variant dropKeys: keys\n"
 +                "property int enterEvents: 0\n"
 +                "width: 100; height: 100\n"
 +                "onEntered: {++enterEvents; dragKeys = drag.keys }\n"
 +                "Item {\n"
 +                    "objectName: \"dragItem\"\n"
 +                    "x: 50; y: 50\n"
 +                    "width: 10; height: 10\n"
 +                    "Drag.keys: [\"red\", \"blue\"]\n"
 +                "}\n"
 +            "}", QUrl());
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
 +    QVERIFY(dropArea);
 +    dropArea->setParentItem(canvas.rootItem());
 +
 +    QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
 +    QVERIFY(dragItem);
 +
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    evaluate<void>(dropArea, "keys = \"blue\"");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "blue");
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "blue");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    evaluate<void>(dropArea, "keys = \"red\"");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "red");
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "red");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    evaluate<void>(dropArea, "keys = \"green\"");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "green");
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "green");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    evaluate<void>(dropArea, "keys = [\"red\", \"green\"]");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "red" << "green");
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "red" << "green");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    evaluate<void>(dragItem, "Drag.keys = []");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    evaluate<void>(dropArea, "keys = []");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList());
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    evaluate<void>(dropArea, "keys = []");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList());
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    evaluate<void>(dragItem, "Drag.keys = [\"red\", \"blue\"]");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "red" << "blue");
 +}
 +
 +void tst_QQuickDropArea::keys_external()
 +{
 +    QQuickCanvas canvas;
 +    QQmlComponent component(&engine);
 +    component.setData(
 +            "import QtQuick 2.0\n"
 +            "DropArea {\n"
 +                "property variant dragKeys\n"
 +                "property variant dropKeys: keys\n"
 +                "property int enterEvents: 0\n"
 +                "width: 100; height: 100\n"
 +                "onEntered: {++enterEvents; dragKeys = drag.keys }\n"
 +            "}", QUrl());
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
 +    dropArea->setParentItem(canvas.rootItem());
 +
 +    QMimeData data;
 +    QQuickCanvas alternateCanvas;
 +
 +    data.setData("text/x-red", "red");
 +    data.setData("text/x-blue", "blue");
 +
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    evaluate<void>(dropArea, "keys = \"text/x-blue\"");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-blue");
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-blue");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    evaluate<void>(dropArea, "keys = \"text/x-red\"");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-red");
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-red");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    evaluate<void>(dropArea, "keys = \"text/x-green\"");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-green");
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-green");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    evaluate<void>(dropArea, "keys = [\"text/x-red\", \"text/x-green\"]");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList() << "text/x-red" << "text/x-green");
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList() << "text/x-red" << "text/x-green");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    data.removeFormat("text/x-red");
 +    data.removeFormat("text/x-blue");
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    evaluate<void>(dropArea, "keys = []");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList());
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    data.setData("text/x-red", "red");
 +    data.setData("text/x-blue", "blue");
 +    QCOMPARE(dropArea->property("keys").toStringList(), QStringList());
 +    QCOMPARE(dropArea->property("dropKeys").toStringList(), QStringList());
 +    evaluate<void>(dropArea, "{ enterEvents = 0; dragKeys = undefined }");
-     QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(dropArea->property("dragKeys").toStringList(), QStringList() << "text/x-red" << "text/x-blue");
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +}
 +
 +void tst_QQuickDropArea::source_internal()
 +{
 +    QQuickCanvas canvas;
 +    QQmlComponent component(&engine);
 +    component.setData(
 +            "import QtQuick 2.0\n"
 +            "DropArea {\n"
 +                "property Item source: drag.source\n"
 +                "property Item eventSource\n"
 +                "width: 100; height: 100\n"
 +                "onEntered: {eventSource = drag.source}\n"
 +                "Item {\n"
 +                    "objectName: \"dragItem\"\n"
 +                    "x: 50; y: 50\n"
 +                    "width: 10; height: 10\n"
 +                "}\n"
 +                "Item { id: dragSource; objectName: \"dragSource\" }\n"
 +            "}", QUrl());
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
 +    QVERIFY(dropArea);
 +    dropArea->setParentItem(canvas.rootItem());
 +
 +    QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
 +    QVERIFY(dragItem);
 +
 +    QQuickItem *dragSource = dropArea->findChild<QQuickItem *>("dragSource");
 +    QVERIFY(dragSource);
 +
 +    QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
 +    QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
 +
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(dragItem));
 +    QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(dragItem));
 +    QCOMPARE(evaluate<QObject *>(dropArea, "eventSource"), static_cast<QObject *>(dragItem));
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
 +    QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
 +
 +
 +    evaluate<void>(dropArea, "{ eventSource = null }");
 +    evaluate<void>(dragItem, "Drag.source = dragSource");
 +
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(dragSource));
 +    QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(dragSource));
 +    QCOMPARE(evaluate<QObject *>(dropArea, "eventSource"), static_cast<QObject *>(dragSource));
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +    QCOMPARE(evaluate<QObject *>(dropArea, "source"), static_cast<QObject *>(0));
 +    QCOMPARE(evaluate<QObject *>(dropArea, "drag.source"), static_cast<QObject *>(0));
 +}
 +
 +// Setting a source can't be emulated using the QWindowSystemInterface API.
 +
 +//void tst_QQuickDropArea::source_external()
 +//{
 +//}
 +
 +void tst_QQuickDropArea::position_internal()
 +{
 +    QQuickCanvas canvas;
 +    QQmlComponent component(&engine);
 +    component.setData(
 +            "import QtQuick 2.0\n"
 +            "DropArea {\n"
 +                "property real dragX: drag.x\n"
 +                "property real dragY: drag.y\n"
 +                "property real eventX\n"
 +                "property real eventY\n"
 +                "property int enterEvents: 0\n"
 +                "property int moveEvents: 0\n"
 +                "width: 100; height: 100\n"
 +                "onEntered: {++enterEvents; eventX = drag.x; eventY = drag.y}\n"
 +                "onPositionChanged: {++moveEvents; eventX = drag.x; eventY = drag.y}\n"
 +                "Item {\n"
 +                    "objectName: \"dragItem\"\n"
 +                    "x: 50; y: 50\n"
 +                    "width: 10; height: 10\n"
 +                "}\n"
 +            "}", QUrl());
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
 +    QVERIFY(dropArea);
 +    dropArea->setParentItem(canvas.rootItem());
 +
 +    QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
 +    QVERIFY(dragItem);
 +
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 0);
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
 +
 +    evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
 +    dragItem->setPos(QPointF(40, 50));
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(40));
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(40));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(40));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
 +
 +    evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
 +    dragItem->setPos(QPointF(75, 25));
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(75));
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(25));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(75));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(25));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(75));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(25));
 +
 +    evaluate<void>(dragItem, "Drag.active = false");
 +}
 +
 +void tst_QQuickDropArea::position_external()
 +{
 +    QQuickCanvas canvas;
 +    QQmlComponent component(&engine);
 +    component.setData(
 +            "import QtQuick 2.0\n"
 +            "DropArea {\n"
 +                "property real dragX: drag.x\n"
 +                "property real dragY: drag.y\n"
 +                "property real eventX\n"
 +                "property real eventY\n"
 +                "property int enterEvents: 0\n"
 +                "property int moveEvents: 0\n"
 +                "width: 100; height: 100\n"
 +                "onEntered: {++enterEvents; eventX = drag.x; eventY = drag.y}\n"
 +                "onPositionChanged: {++moveEvents; eventX = drag.x; eventY = drag.y}\n"
 +            "}", QUrl());
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
 +    QVERIFY(dropArea);
 +    dropArea->setParentItem(canvas.rootItem());
 +
 +    QMimeData data;
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(40, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
 +
 +    evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(75, 25));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(40, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(40));
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(40));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(50));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(40));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(50));
 +
 +    evaluate<void>(dropArea, "{ enterEvents = 0; moveEvents = 0; eventX = -1; eventY = -1 }");
-     QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(75, 25));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(75, 25), Qt::CopyAction);
 +    QCOMPARE(evaluate<int>(dropArea, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea, "moveEvents"), 1);
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.x"), qreal(75));
 +    QCOMPARE(evaluate<qreal>(dropArea, "drag.y"), qreal(25));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragX"), qreal(75));
 +    QCOMPARE(evaluate<qreal>(dropArea, "dragY"), qreal(25));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventX"), qreal(75));
 +    QCOMPARE(evaluate<qreal>(dropArea, "eventY"), qreal(25));
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrop(&canvas, &data, QPoint(75, 25), Qt::CopyAction);
 +}
 +
 +void tst_QQuickDropArea::drop_internal()
 +{
 +    QQuickCanvas canvas;
 +    QQmlComponent component(&engine);
 +    component.setData(
 +            "import QtQuick 2.0\n"
 +            "DropArea {\n"
 +                "property bool accept: false\n"
 +                "property bool setAccepted: false\n"
 +                "property bool acceptDropAction: false\n"
 +                "property bool setDropAction: false\n"
 +                "property int dropAction: Qt.IgnoreAction\n"
 +                "property int proposedAction: Qt.IgnoreAction\n"
 +                "property int supportedActions: Qt.IgnoreAction\n"
 +                "property int dropEvents: 0\n"
 +                "width: 100; height: 100\n"
 +                "onDropped: {\n"
 +                    "++dropEvents\n"
 +                    "supportedActions = drop.supportedActions\n"
 +                    "proposedAction = drop.action\n"
 +                    "if (setDropAction)\n"
 +                        "drop.action = dropAction\n"
 +                    "if (acceptDropAction)\n"
 +                        "drop.accept(dropAction)\n"
 +                    "else if (setAccepted)\n"
 +                        "drop.accepted = accept\n"
 +                    "else if (accept)\n"
 +                        "drop.accept()\n"
 +                "}\n"
 +                "Item {\n"
 +                    "objectName: \"dragItem\"\n"
 +                    "x: 50; y: 50\n"
 +                    "width: 10; height: 10\n"
 +                "}\n"
 +            "}", QUrl());
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickItem *dropArea = qobject_cast<QQuickItem *>(object.data());
 +    QVERIFY(dropArea);
 +    dropArea->setParentItem(canvas.rootItem());
 +
 +    QQuickItem *dragItem = dropArea->findChild<QQuickItem *>("dragItem");
 +    QVERIFY(dragItem);
 +
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::IgnoreAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
 +
 +    evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
 +    evaluate<void>(dropArea, "{ accept = true; setDropAction = true; dropAction = Qt.LinkAction }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
 +
 +    evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
 +    evaluate<void>(dropArea, "{ setAccepted = true; }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
 +
 +    evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
 +    evaluate<void>(dropArea, "{ accept = false; setAccepted = true; }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::IgnoreAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
 +
 +    evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
 +    evaluate<void>(dropArea, "{ setAccepted = false; setDropAction = false; acceptDropAction = true; }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
 +
 +    evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
 +    evaluate<void>(dropArea, "{ acceptDropAction = false; dropAction = Qt.IgnoreAction; accept = true }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
 +
 +    evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
 +    evaluate<void>(dropArea, "{ setAccepted = true }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
 +
 +    evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
 +    evaluate<void>(dropArea, "{ setAccepted = false }");
 +    evaluate<void>(dragItem, "Drag.supportedActions = Qt.LinkAction");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
 +
 +    evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
 +    evaluate<void>(dropArea, "{ setAccepted = true }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::MoveAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::MoveAction));
 +
 +    evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
 +    evaluate<void>(dropArea, "{ setAccepted = false }");
 +    evaluate<void>(dragItem, "Drag.proposedAction = Qt.LinkAction");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::LinkAction));
 +
 +    evaluate<void>(dropArea, "{ dropEvents = 0; proposedAction = Qt.IgnoreAction; supportedActions = Qt.IgnoreAction }");
 +    evaluate<void>(dropArea, "{ setAccepted = true }");
 +    evaluate<void>(dragItem, "Drag.active = true");
 +    QCOMPARE(evaluate<int>(dragItem, "Drag.drop()"), int(Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "dropEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea, "supportedActions"), int(Qt::LinkAction));
 +    QCOMPARE(evaluate<int>(dropArea, "proposedAction"), int(Qt::LinkAction));
 +}
 +
 +// Setting the supportedActions can't be emulated using the QWindowSystemInterface API.
 +
 +//void tst_QQuickDropArea::drop_external()
 +//{
 +//}
 +
 +void tst_QQuickDropArea::simultaneousDrags()
 +{
 +    QQuickCanvas canvas;
 +    QQmlComponent component(&engine);
 +    component.setData(
 +            "import QtQuick 2.0\n"
 +            "DropArea {\n"
 +                "property int enterEvents: 0\n"
 +                "property int exitEvents: 0\n"
 +                "width: 100; height: 100\n"
 +                "keys: [\"red\", \"text/x-red\"]\n"
 +                "onEntered: {++enterEvents}\n"
 +                "onExited: {++exitEvents}\n"
 +                "DropArea {\n"
 +                    "objectName: \"dropArea2\"\n"
 +                    "property int enterEvents: 0\n"
 +                    "property int exitEvents: 0\n"
 +                    "width: 100; height: 100\n"
 +                    "keys: [\"blue\", \"text/x-blue\"]\n"
 +                    "onEntered: {++enterEvents}\n"
 +                    "onExited: {++exitEvents}\n"
 +                "}\n"
 +                "Item {\n"
 +                    "objectName: \"dragItem1\"\n"
 +                    "x: 50; y: 50\n"
 +                    "width: 10; height: 10\n"
 +                    "Drag.keys: [\"red\", \"blue\"]"
 +                "}\n"
 +                "Item {\n"
 +                    "objectName: \"dragItem2\"\n"
 +                    "x: 50; y: 50\n"
 +                    "width: 10; height: 10\n"
 +                    "Drag.keys: [\"red\", \"blue\"]"
 +                "}\n"
 +            "}", QUrl());
 +
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickItem *dropArea1 = qobject_cast<QQuickItem *>(object.data());
 +    QVERIFY(dropArea1);
 +    dropArea1->setParentItem(canvas.rootItem());
 +
 +    QQuickItem *dropArea2 = dropArea1->findChild<QQuickItem *>("dropArea2");
 +    QVERIFY(dropArea2);
 +
 +    QQuickItem *dragItem1 = dropArea1->findChild<QQuickItem *>("dragItem1");
 +    QVERIFY(dragItem1);
 +
 +    QQuickItem *dragItem2 = dropArea1->findChild<QQuickItem *>("dragItem2");
 +    QVERIFY(dragItem2);
 +
 +    QMimeData data;
 +    data.setData("text/x-red", "red");
 +    data.setData("text/x-blue", "blue");
 +
 +    QQuickCanvas alternateCanvas;
 +
 +    // Mixed internal drags.
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem1, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem2, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dragItem2, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dragItem2, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dragItem1, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem2, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    // internal then external.
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem1, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dragItem1, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    // external then internal.
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem2, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dragItem2, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dragItem2, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem2, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    // Different acceptance
 +    evaluate<void>(dragItem1, "Drag.keys = \"red\"");
 +    evaluate<void>(dragItem2, "Drag.keys = \"blue\"");
 +    data.removeFormat("text/x-red");
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem1, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem2, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem2, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem2, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem1, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem2, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
 +
 +    // internal then external
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem1, "Drag.active = true");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
-     QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
-     QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&canvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 1);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dragItem1, "Drag.active = false");
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 1);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), true);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 0);
 +
 +    evaluate<void>(dropArea1, "{ enterEvents = 0; exitEvents = 0 }");
 +    evaluate<void>(dropArea2, "{ enterEvents = 0; exitEvents = 0 }");
-     QWindowSystemInterface::handleDrop(&alternateCanvas, &data, QPoint(50, 50));
++    QWindowSystemInterface::handleDrag(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +    QCOMPARE(evaluate<bool>(dropArea1, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea1, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea1, "exitEvents"), 0);
 +    QCOMPARE(evaluate<bool>(dropArea2, "containsDrag"), false);
 +    QCOMPARE(evaluate<int>(dropArea2, "enterEvents"), 0);
 +    QCOMPARE(evaluate<int>(dropArea2, "exitEvents"), 1);
 +
++    QWindowSystemInterface::handleDrop(&alternateCanvas, &data, QPoint(50, 50), Qt::CopyAction);
 +}
 +
 +QTEST_MAIN(tst_QQuickDropArea)
 +
 +#include "tst_qquickdroparea.moc"
index d156ed0,0000000..c0f2b02
mode 100644,000000..100644
--- /dev/null
@@@ -1,5075 -1,0 +1,5310 @@@
-     component.setData("import QtQuick 2.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include <QtTest/QtTest>
 +#include <QtCore/qstringlistmodel.h>
 +#include <QtQuick/qquickview.h>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtQml/qqmlcontext.h>
 +#include <QtQml/qqmlexpression.h>
 +#include <QtQml/qqmlincubator.h>
 +#include <QtQuick/private/qquickitem_p.h>
 +#include <QtQuick/private/qquickgridview_p.h>
 +#include <QtQuick/private/qquicktext_p.h>
 +#include <QtQuick/private/qquickvisualitemmodel_p.h>
 +#include <QtQml/private/qquicklistmodel_p.h>
 +#include <QtQml/private/qlistmodelinterface_p.h>
 +#include "../../shared/util.h"
 +#include "../shared/viewtestutil.h"
 +#include "../shared/visualtestutil.h"
 +#include <QtGui/qguiapplication.h>
 +
 +Q_DECLARE_METATYPE(Qt::LayoutDirection)
 +Q_DECLARE_METATYPE(QQuickGridView::Flow)
 +
 +using namespace QQuickViewTestUtil;
 +using namespace QQuickVisualTestUtil;
 +
 +class tst_QQuickGridView : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_QQuickGridView();
 +
 +private slots:
 +    void items();
 +    void changed();
 +    void inserted();
 +    void inserted_more();
 +    void inserted_more_data();
 +    void insertBeforeVisible();
 +    void insertBeforeVisible_data();
 +    void removed();
 +    void removed_more();
 +    void removed_more_data();
 +    void addOrRemoveBeforeVisible();
 +    void addOrRemoveBeforeVisible_data();
 +    void clear();
 +    void moved();
 +    void moved_data();
 +    void multipleChanges();
 +    void multipleChanges_data();
 +    void swapWithFirstItem();
 +    void changeFlow();
 +    void currentIndex();
 +    void noCurrentIndex();
 +    void defaultValues();
 +    void properties();
 +    void propertyChanges();
 +    void componentChanges();
 +    void modelChanges();
 +    void positionViewAtIndex();
 +    void positionViewAtIndex_rightToLeft();
 +    void mirroring();
 +    void snapping();
 +    void resetModel();
 +    void enforceRange();
 +    void enforceRange_rightToLeft();
 +    void QTBUG_8456();
 +    void manualHighlight();
 +    void footer();
 +    void footer_data();
 +    void header();
 +    void header_data();
 +    void resizeViewAndRepaint();
 +    void changeColumnCount();
 +    void indexAt_itemAt_data();
 +    void indexAt_itemAt();
 +    void onAdd();
 +    void onAdd_data();
 +    void onRemove();
 +    void onRemove_data();
 +    void columnCount();
 +    void margins();
 +    void creationContext();
 +    void snapToRow_data();
 +    void snapToRow();
 +    void snapOneRow_data();
 +    void snapOneRow();
 +    void unaligned();
 +    void cacheBuffer();
 +    void asynchronous();
 +    void unrequestedVisibility();
 +
 +    void populateTransitions();
 +    void populateTransitions_data();
 +    void addTransitions();
 +    void addTransitions_data();
 +    void moveTransitions();
 +    void moveTransitions_data();
 +    void removeTransitions();
 +    void removeTransitions_data();
++    void displacedTransitions();
++    void displacedTransitions_data();
 +    void multipleTransitions();
 +    void multipleTransitions_data();
 +
 +private:
 +    QList<int> toIntList(const QVariantList &list);
 +    void matchIndexLists(const QVariantList &indexLists, const QList<int> &expectedIndexes);
 +    void matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList<int> &expectedIndexes);
 +    void matchItemLists(const QVariantList &itemLists, const QList<QQuickItem *> &expectedItems);
 +};
 +
 +tst_QQuickGridView::tst_QQuickGridView()
 +{
 +}
 +
 +void tst_QQuickGridView::items()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    model.addItem("Fred", "12345");
 +    model.addItem("John", "2345");
 +    model.addItem("Bob", "54321");
 +    model.addItem("Billy", "22345");
 +    model.addItem("Sam", "2945");
 +    model.addItem("Ben", "04321");
 +    model.addItem("Jim", "0780");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QTRY_COMPARE(gridview->count(), model.count());
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +    QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
 +
 +    for (int i = 0; i < model.count(); ++i) {
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QTRY_VERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QTRY_VERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +
 +    // set an empty model and confirm that items are destroyed
 +    QaimModel model2;
 +    ctxt->setContextProperty("testModel", &model2);
 +
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    QTRY_VERIFY(itemCount == 0);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::changed()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    model.addItem("Fred", "12345");
 +    model.addItem("John", "2345");
 +    model.addItem("Bob", "54321");
 +    model.addItem("Billy", "22345");
 +    model.addItem("Sam", "2945");
 +    model.addItem("Ben", "04321");
 +    model.addItem("Jim", "0780");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    qApp->processEvents();
 +
 +    QQuickFlickable *gridview = findItem<QQuickFlickable>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    model.modifyItem(1, "Will", "9876");
 +    QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(1));
 +    QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(1));
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::inserted()
 +{
 +    QQuickView *canvas = createView();
 +    canvas->show();
 +
 +    QaimModel model;
 +    model.addItem("Fred", "12345");
 +    model.addItem("John", "2345");
 +    model.addItem("Bob", "54321");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    model.insertItem(1, "Will", "9876");
 +
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +    QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
 +
 +    QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(1));
 +    QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(1));
 +
 +    // Checks that onAdd is called
 +    int added = canvas->rootObject()->property("added").toInt();
 +    QTRY_COMPARE(added, 1);
 +
 +    // Confirm items positioned correctly
 +    for (int i = 0; i < model.count(); ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QTRY_COMPARE(item->x(), (i%3)*80.0);
 +        QTRY_COMPARE(item->y(), (i/3)*60.0);
 +    }
 +
 +    model.insertItem(0, "Foo", "1111"); // zero index, and current item
 +
 +    QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
 +
 +    name = findItem<QQuickText>(contentItem, "textName", 0);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(0));
 +    number = findItem<QQuickText>(contentItem, "textNumber", 0);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(0));
 +
 +    QTRY_COMPARE(gridview->currentIndex(), 1);
 +
 +    // Confirm items positioned correctly
 +    for (int i = 0; i < model.count(); ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QTRY_VERIFY(item->x() == (i%3)*80);
 +        QTRY_VERIFY(item->y() == (i/3)*60);
 +    }
 +
 +    for (int i = model.count(); i < 30; ++i)
 +        model.insertItem(i, "Hello", QString::number(i));
 +
 +    gridview->setContentY(120);
 +
 +    // Insert item outside visible area
 +    model.insertItem(1, "Hello", "1324");
 +
 +    QTRY_VERIFY(gridview->contentY() == 120);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::inserted_more()
 +{
 +    QFETCH(qreal, contentY);
 +    QFETCH(int, insertIndex);
 +    QFETCH(int, insertCount);
 +    QFETCH(qreal, itemsOffsetAfterMove);
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    gridview->setContentY(contentY);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    QList<QPair<QString, QString> > newData;
 +    for (int i=0; i<insertCount; i++)
 +        newData << qMakePair(QString("value %1").arg(i), QString::number(i));
 +    model.insertItems(insertIndex, newData);
 +    QTRY_COMPARE(gridview->property("count").toInt(), model.count());
 +
 +    // check visibleItems.first() is in correct position
 +    QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item0);
 +    QCOMPARE(item0->y(), 0.0);
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    int firstVisibleIndex = -1;
 +    for (int i=0; i<items.count(); i++) {
 +        if (items[i]->y() >= contentY) {
 +            QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +            firstVisibleIndex = e.evaluate().toInt();
 +            break;
 +        }
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // Confirm items positioned correctly and indexes correct
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    QQuickText *name;
 +    QQuickText *number;
 +    for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +
 +        QCOMPARE(item->x(), (i%3)*80.0);
 +        QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
 +
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QCOMPARE(name->text(), model.name(i));
 +        number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QVERIFY(number != 0);
 +        QCOMPARE(number->text(), model.number(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::inserted_more_data()
 +{
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<int>("insertIndex");
 +    QTest::addColumn<int>("insertCount");
 +    QTest::addColumn<qreal>("itemsOffsetAfterMove");
 +
 +    QTest::newRow("add 1, before visible items")
 +            << 120.0     // show 6-23
 +            << 5 << 1
 +            << 0.0;   // insert 1 above first visible, grid is rearranged; first visible moves forward within its row
 +                      // new 1st visible item is at 0
 +
 +    QTest::newRow("add 2, before visible items")
 +            << 120.0     // show 6-23
 +            << 5 << 2
 +            << 0.0;   // insert 2 above first visible, grid is rearranged; first visible moves forward within its row
 +
 +    QTest::newRow("add 3, before visible items")
 +            << 120.0     // show 6-23
 +            << 5 << 3
 +            << -60.0;   // insert 3 (1 row) above first visible in negative pos, first visible does not move
 +
 +    QTest::newRow("add 5, before visible items")
 +            << 120.0     // show 6-23
 +            << 5 << 5
 +            << -60.0;   // insert 1 row + 2 items above first visible, 1 row added at negative pos,
 +                        // grid is rearranged and first visible moves forward within its row
 +
 +    QTest::newRow("add 6, before visible items")
 +            << 120.0     // show 6-23
 +            << 5 << 6
 +            << -60.0 * 2;   // insert 2 rows above first visible in negative pos, first visible does not move
 +
 +
 +
 +   QTest::newRow("add 1, at start of visible, content at start")
 +            << 0.0
 +            << 0 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add multiple, at start of visible, content at start")
 +            << 0.0
 +            << 0 << 3
 +            << 0.0;
 +
 +    QTest::newRow("add 1, at start of visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 6 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add multiple, at start of visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 6 << 3
 +            << 0.0;
 +
 +
 +    QTest::newRow("add 1, at end of visible, content at start")
 +            << 0.0
 +            << 17 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add 1, at end of visible, content at start")
 +            << 0.0
 +            << 17 << 3
 +            << 0.0;
 +
 +    QTest::newRow("add 1, at end of visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 23 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add multiple, at end of visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 23 << 3
 +            << 0.0;
 +
 +
 +    QTest::newRow("add 1, after visible, content at start")
 +            << 0.0
 +            << 20 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add 1, after visible, content at start")
 +            << 0.0
 +            << 20 << 3
 +            << 0.0;
 +
 +    QTest::newRow("add 1, after visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 24 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add multiple, after visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 24 << 3
 +            << 0.0;
 +}
 +
 +void tst_QQuickGridView::insertBeforeVisible()
 +{
 +    QFETCH(int, insertIndex);
 +    QFETCH(int, insertCount);
 +    QFETCH(int, cacheBuffer);
 +
 +    QQuickText *name;
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    gridview->setCacheBuffer(cacheBuffer);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    // trigger a refill (not just setting contentY) so that the visibleItems grid is updated
 +    int firstVisibleIndex = 12;     // move to an index where the top item is not visible
 +    gridview->setContentY(firstVisibleIndex/3 * 60.0);
 +    gridview->setCurrentIndex(firstVisibleIndex);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    QTRY_COMPARE(gridview->currentIndex(), firstVisibleIndex);
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex);
 +    QVERIFY(item);
 +    QCOMPARE(item->y(), gridview->contentY());
 +
 +    QList<QPair<QString, QString> > newData;
 +    for (int i=0; i<insertCount; i++)
 +        newData << qMakePair(QString("value %1").arg(i), QString::number(i));
 +    model.insertItems(insertIndex, newData);
 +    QTRY_COMPARE(gridview->property("count").toInt(), model.count());
 +
 +    // now, moving to the top of the view should position the inserted items correctly
 +    int itemsOffsetAfterMove = (insertCount / 3) * -60.0;
 +    gridview->setCurrentIndex(0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +    QTRY_COMPARE(gridview->currentIndex(), 0);
 +    QTRY_COMPARE(gridview->contentY(), 0.0 + itemsOffsetAfterMove);
 +
 +    // Confirm items positioned correctly and indexes correct
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), (i%3)*80.0);
 +        QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::insertBeforeVisible_data()
 +{
 +    QTest::addColumn<int>("insertIndex");
 +    QTest::addColumn<int>("insertCount");
 +    QTest::addColumn<int>("cacheBuffer");
 +
 +    QTest::newRow("insert 1 at 0, 0 buffer") << 0 << 1 << 0;
 +    QTest::newRow("insert 1 at 0, 100 buffer") << 0 << 1 << 100;
 +    QTest::newRow("insert 1 at 0, 500 buffer") << 0 << 1 << 500;
 +
 +    QTest::newRow("insert 1 at 1, 0 buffer") << 1 << 1 << 0;
 +    QTest::newRow("insert 1 at 1, 100 buffer") << 1 << 1 << 100;
 +    QTest::newRow("insert 1 at 1, 500 buffer") << 1 << 1 << 500;
 +
 +    QTest::newRow("insert multiple at 0, 0 buffer") << 0 << 6 << 0;
 +    QTest::newRow("insert multiple at 0, 100 buffer") << 0 << 6 << 100;
 +    QTest::newRow("insert multiple at 0, 500 buffer") << 0 << 6 << 500;
 +
 +    QTest::newRow("insert multiple at 1, 0 buffer") << 1 << 6 << 0;
 +    QTest::newRow("insert multiple at 1, 100 buffer") << 1 << 6 << 100;
 +    QTest::newRow("insert multiple at 1, 500 buffer") << 1 << 6 << 500;
 +}
 +
 +void tst_QQuickGridView::removed()
 +{
 +    QQuickView *canvas = createView();
 +    canvas->show();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 40; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    model.removeItem(1);
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(1));
 +    QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(1));
 +
 +
 +    // Checks that onRemove is called
 +    QString removed = canvas->rootObject()->property("removed").toString();
 +    QTRY_COMPARE(removed, QString("Item1"));
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item->x() == (i%3)*80);
 +        QTRY_VERIFY(item->y() == (i/3)*60);
 +    }
 +
 +    // Remove first item (which is the current item);
 +    model.removeItem(0);
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    name = findItem<QQuickText>(contentItem, "textName", 0);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(0));
 +    number = findItem<QQuickText>(contentItem, "textNumber", 0);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(0));
 +
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item->x() == (i%3)*80);
 +        QTRY_VERIFY(item->y() == (i/3)*60);
 +    }
 +
 +    // Remove items not visible
 +    model.removeItem(25);
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item->x() == (i%3)*80);
 +        QTRY_VERIFY(item->y() == (i/3)*60);
 +    }
 +
 +    // Remove items before visible
 +    gridview->setContentY(120);
 +    gridview->setCurrentIndex(10);
 +
 +    // Setting currentIndex above shouldn't cause view to scroll
 +    QTRY_COMPARE(gridview->contentY(), 120.0);
 +
 +    model.removeItem(1);
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    // Confirm items positioned correctly
 +    for (int i = 6; i < 18; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item->x() == (i%3)*80);
 +        QTRY_VERIFY(item->y() == (i/3)*60);
 +    }
 +
 +    // Remove currentIndex
 +    QQuickItem *oldCurrent = gridview->currentItem();
 +    model.removeItem(9);
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    QTRY_COMPARE(gridview->currentIndex(), 9);
 +    QTRY_VERIFY(gridview->currentItem() != oldCurrent);
 +
 +    gridview->setContentY(0);
 +    // let transitions settle.
 +    QTest::qWait(300);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QTRY_VERIFY(item->x() == (i%3)*80);
 +        QTRY_VERIFY(item->y() == (i/3)*60);
 +    }
 +
 +    // remove item outside current view.
 +    gridview->setCurrentIndex(32);
 +    gridview->setContentY(240);
 +
 +    model.removeItem(30);
 +    QTRY_VERIFY(gridview->currentIndex() == 31);
 +
 +    // remove current item beyond visible items.
 +    gridview->setCurrentIndex(20);
 +    gridview->setContentY(0);
 +    model.removeItem(20);
 +
 +    QTRY_COMPARE(gridview->currentIndex(), 20);
 +    QTRY_VERIFY(gridview->currentItem() != 0);
 +
 +    // remove item before current, but visible
 +    gridview->setCurrentIndex(8);
 +    gridview->setContentY(240);
 +    oldCurrent = gridview->currentItem();
 +    model.removeItem(6);
 +
 +    QTRY_COMPARE(gridview->currentIndex(), 7);
 +    QTRY_VERIFY(gridview->currentItem() == oldCurrent);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::removed_more()
 +{
 +    QFETCH(qreal, contentY);
 +    QFETCH(int, removeIndex);
 +    QFETCH(int, removeCount);
 +    QFETCH(qreal, itemsOffsetAfterMove);
 +    QFETCH(QString, firstVisible);
 +
 +    QQuickText *name;
 +    QQuickText *number;
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    gridview->setContentY(contentY);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    model.removeItems(removeIndex, removeCount);
 +    QTRY_COMPARE(gridview->property("count").toInt(), model.count());
 +
 +    QString firstName;
 +    int firstVisibleIndex = -1;
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    for (int i=0; i<items.count(); i++) {
 +        if (items[i]->y() >= contentY) {
 +            QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +            firstVisibleIndex = e.evaluate().toInt();
 +            QQmlExpression en(qmlContext(items[i]), items[i], "name");
 +            firstName = en.evaluate().toString();
 +            break;
 +        }
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +    QCOMPARE(firstName, firstVisible);
 +
 +    // Confirm items positioned correctly and indexes correct
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +
 +        QTRY_COMPARE(item->x(), (i%3)*80.0);
 +        QTRY_COMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
 +
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QVERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::removed_more_data()
 +{
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<int>("removeIndex");
 +    QTest::addColumn<int>("removeCount");
 +    QTest::addColumn<qreal>("itemsOffsetAfterMove");
 +    QTest::addColumn<QString>("firstVisible");
 +
 +    QTest::newRow("remove 1, before visible items")
 +            << 120.0     // show 6-23
 +            << 2 << 1
 +            << 0.0 << "Item7";
 +
 +    QTest::newRow("remove 1, before visible position")
 +            << 120.0     // show 6-23
 +            << 3 << 1
 +            << 0.0 << "Item7";
 +
 +    QTest::newRow("remove multiple, all before visible items")
 +            << 120.0
 +            << 1 << 3
 +            << 60.0 << "Item6";    // removed top row, slide down by 1 row
 +
 +    QTest::newRow("remove multiple, all before visible items, remove item 0")
 +            << 120.0
 +            << 0 << 4
 +            << 60.0 << "Item7";    // removed top row, slide down by 1 row
 +
 +    QTest::newRow("remove multiple rows, all before visible items")
 +            << 240.0     // show 12-29
 +            << 1 << 7
 +            << 120.0 << "Item13";
 +
 +    QTest::newRow("remove one row before visible, content y not on item border")
 +            << 100.0
 +            << 0 << 3
 +            << 60.0 << "Item6"; // 1 row removed
 +
 +    QTest::newRow("remove mix of visible/non-visible")
 +            << 120.0     // show 6-23
 +            << 2 << 3
 +            << 60.0 << "Item6"; // 1 row removed
 +
 +
 +    // remove 3,4,5 before the visible pos, first row moves down to just before the visible pos,
 +    // items 6,7 are removed from view, item 8 slides up to original pos of item 6 (120px)
 +    QTest::newRow("remove multiple, mix of items from before and within visible items")
 +            << 120.0
 +            << 3 << 5
 +            << 60.0 << "Item8";    // adjust for the 1 row removed before the visible
 +
 +    QTest::newRow("remove multiple, mix of items from before and within visible items, remove item 0")
 +            << 120.0
 +            << 0 << 8
 +            << 60.0 * 2 << "Item8";    // adjust for the 2 rows removed before the visible
 +
 +
 +    QTest::newRow("remove 1, from start of visible, content at start")
 +            << 0.0
 +            << 0 << 1
 +            << 0.0 << "Item1";
 +
 +    QTest::newRow("remove multiple, from start of visible, content at start")
 +            << 0.0
 +            << 0 << 3
 +            << 0.0 << "Item3";
 +
 +    QTest::newRow("remove 1, from start of visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 4 << 1
 +            << 0.0 << "Item7";
 +
 +    QTest::newRow("remove multiple, from start of visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 4 << 3
 +            << 0.0 << "Item9";
 +
 +
 +    QTest::newRow("remove 1, from middle of visible, content at start")
 +            << 0.0
 +            << 10 << 1
 +            << 0.0 << "Item0";
 +
 +    QTest::newRow("remove multiple, from middle of visible, content at start")
 +            << 0.0
 +            << 10 << 5
 +            << 0.0 << "Item0";
 +
 +    QTest::newRow("remove 1, from middle of visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 10 << 1
 +            << 0.0 << "Item6";
 +
 +    QTest::newRow("remove multiple, from middle of visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 10 << 5
 +            << 0.0 << "Item6";
 +
 +
 +    QTest::newRow("remove 1, after visible, content at start")
 +            << 0.0
 +            << 16 << 1
 +            << 0.0 << "Item0";
 +
 +    QTest::newRow("remove multiple, after visible, content at start")
 +            << 0.0
 +            << 16 << 5
 +            << 0.0 << "Item0";
 +
 +    QTest::newRow("remove 1, after visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 16+4 << 1
 +            << 0.0 << "Item6";
 +
 +    QTest::newRow("remove multiple, after visible, content not at start")
 +            << 120.0     // show 6-23
 +            << 16+4 << 5
 +            << 0.0 << "Item6";
 +
 +    QTest::newRow("remove multiple, mix of items from within and after visible items")
 +            << 120.0     // show 6-23
 +            << 20 << 5
 +            << 0.0 << "Item6";
 +}
 +
 +void tst_QQuickGridView::addOrRemoveBeforeVisible()
 +{
 +    // QTBUG-21588: ensure re-layout is done on grid after adding or removing
 +    // items from before the visible area
 +
 +    QFETCH(bool, doAdd);
 +    QFETCH(qreal, newTopContentY);
 +
 +    QQuickView *canvas = createView();
 +    canvas->show();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
 +    QTRY_COMPARE(name->text(), QString("Item0"));
 +
 +    gridview->setCurrentIndex(0);
 +    qApp->processEvents();
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    // scroll down until item 0 is no longer drawn
 +    // (bug not triggered if we just move using content y, since that doesn't
 +    // refill and change the visible items)
 +    gridview->setCurrentIndex(24);
 +    qApp->processEvents();
 +
 +    QTRY_COMPARE(gridview->currentIndex(), 24);
 +    QTRY_COMPARE(gridview->contentY(), 220.0);
 +
 +    QTest::qWait(100);  // wait for refill to complete
 +    QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 0));  // 0 shouldn't be visible
 +
 +    if (doAdd) {
 +        model.insertItem(0, "New Item", "New Item number");
 +        QTRY_COMPARE(gridview->count(), 31);
 +    } else {
 +        model.removeItem(0);
 +        QTRY_COMPARE(gridview->count(), 29);
 +    }
 +
 +    // scroll back up and item 0 should be gone
 +    gridview->setCurrentIndex(0);
 +    qApp->processEvents();
 +    QTRY_COMPARE(gridview->currentIndex(), 0);
 +    QTRY_COMPARE(gridview->contentY(), newTopContentY);
 +
 +    name = findItem<QQuickText>(contentItem, "textName", 0);
 +    if (doAdd)
 +        QCOMPARE(name->text(), QString("New Item"));
 +    else
 +        QCOMPARE(name->text(), QString("Item1"));
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", i));
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QTRY_VERIFY(item->x() == (i%3)*80);
 +        QTRY_VERIFY(item->y() == (i/3)*60 + newTopContentY);
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::addOrRemoveBeforeVisible_data()
 +{
 +    QTest::addColumn<bool>("doAdd");
 +    QTest::addColumn<qreal>("newTopContentY");
 +
 +    QTest::newRow("add") << true << -60.0;
 +    QTest::newRow("remove") << false << -60.0;
 +}
 +
 +void tst_QQuickGridView::clear()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QVERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    model.clear();
 +
 +    QVERIFY(gridview->count() == 0);
 +    QVERIFY(gridview->currentItem() == 0);
 +    QVERIFY(gridview->contentY() == 0);
 +    QVERIFY(gridview->currentIndex() == -1);
 +
 +    // confirm sanity when adding an item to cleared list
 +    model.addItem("New", "1");
 +    QTRY_COMPARE(gridview->count(), 1);
 +    QVERIFY(gridview->currentItem() != 0);
 +    QVERIFY(gridview->currentIndex() == 0);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::moved()
 +{
 +    QFETCH(qreal, contentY);
 +    QFETCH(int, from);
 +    QFETCH(int, to);
 +    QFETCH(int, count);
 +    QFETCH(qreal, itemsOffsetAfterMove);
 +
 +    QQuickText *name;
 +    QQuickText *number;
 +    QScopedPointer<QQuickView> canvas(createView());
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    QQuickItem *currentItem = gridview->currentItem();
 +    QTRY_VERIFY(currentItem != 0);
 +
 +    if (contentY != 0) {
 +        gridview->setContentY(contentY);
 +        QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +    }
 +
 +    model.moveItems(from, to, count);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    // Confirm items positioned correctly and indexes correct
 +    int firstVisibleIndex = qCeil(contentY / 60.0) * 3;
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        if (i >= firstVisibleIndex + 18)    // index has moved out of view
 +            continue;
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +
 +        QTRY_COMPARE(item->x(), (i%3)*80.0);
 +        QTRY_COMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
 +
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QVERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +
 +        // current index should have been updated
 +        if (item == currentItem)
 +            QTRY_COMPARE(gridview->currentIndex(), i);
 +    }
 +}
 +
 +void tst_QQuickGridView::moved_data()
 +{
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<int>("from");
 +    QTest::addColumn<int>("to");
 +    QTest::addColumn<int>("count");
 +    QTest::addColumn<qreal>("itemsOffsetAfterMove");
 +
 +    // model starts with 30 items, each 80x60, in area 240x320
 +    // 18 items should be visible at a time
 +
 +    // The first visible item should not move upwards and out of the view
 +    // if items are moved/removed before it.
 +
 +
 +    QTest::newRow("move 1 forwards, within visible items")
 +            << 0.0
 +            << 1 << 8 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 forwards, from non-visible -> visible")
 +            << 120.0     // show 6-23
 +            << 1 << 23 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
 +            << 120.0     // // show 6-23
 +            << 0 << 6 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 forwards, from visible -> non-visible")
 +            << 0.0
 +            << 1 << 20 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 forwards, from visible -> non-visible (move first item)")
 +            << 0.0
 +            << 0 << 20 << 1
 +            << 0.0;
 +
 +
 +    QTest::newRow("move 1 backwards, within visible items")
 +            << 0.0
 +            << 10 << 5 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 backwards, within visible items (to first index)")
 +            << 0.0
 +            << 10 << 0 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 backwards, from non-visible -> visible")
 +            << 0.0
 +            << 28 << 8 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 backwards, from non-visible -> visible (move last item)")
 +            << 0.0
 +            << 29 << 14 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 backwards, from visible -> non-visible")
 +            << 120.0     // show 6-23
 +            << 7 << 1 << 1
 +            << 0.0;     // only 1 item moved back, so items shift accordingly and first row doesn't move
 +
 +    QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
 +            << 120.0     // show 6-23
 +            << 7 << 0 << 1
 +            << 0.0;     // only 1 item moved back, so items shift accordingly and first row doesn't move
 +
 +
 +    QTest::newRow("move multiple forwards, within visible items")
 +            << 0.0
 +            << 0 << 5 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple backwards, within visible items (move first item)")
 +            << 0.0
 +            << 10 << 0 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple forwards, before visible items")
 +            << 120.0     // show 6-23
 +            << 3 << 4 << 3      // 3, 4, 5 move to after 6
 +            << 60.0;      // row of 3,4,5 has moved down
 +
 +    QTest::newRow("move multiple forwards, from non-visible -> visible")
 +            << 120.0     // show 6-23
 +            << 1 << 6 << 3
 +            << 60.0; // 1st row (it's above visible area) disappears, 0 drops down 1 row, first visible item (6) stays where it is
 +
 +    QTest::newRow("move multiple forwards, from non-visible -> visible (move first item)")
 +            << 120.0     // show 6-23
 +            << 0 << 6 << 3
 +            << 60.0;    // top row moved and shifted to below 3rd row, all items should shift down by 1 row
 +
 +    QTest::newRow("move multiple forwards, mix of non-visible/visible")
 +            << 120.0
 +            << 3 << 16 << 6
 +            << 60.0;    // top two rows removed, third row is now the first visible
 +
 +    QTest::newRow("move multiple forwards, to bottom of view")
 +            << 0.0
 +            << 5 << 13 << 5
 +            << 0.0;
 +
 +    QTest::newRow("move multiple forwards, to bottom of view, first row -> last")
 +            << 0.0
 +            << 0 << 15 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple forwards, to bottom of view, content y not 0")
 +            << 120.0
 +            << 5+4 << 13+4 << 5
 +            << 0.0;
 +
 +    QTest::newRow("move multiple forwards, from visible -> non-visible")
 +            << 0.0
 +            << 1 << 16 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple forwards, from visible -> non-visible (move first item)")
 +            << 0.0
 +            << 0 << 16 << 3
 +            << 0.0;
 +
 +
 +    QTest::newRow("move multiple backwards, within visible items")
 +            << 0.0
 +            << 4 << 1 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple backwards, from non-visible -> visible")
 +            << 0.0
 +            << 20 << 4 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple backwards, from non-visible -> visible (move last item)")
 +            << 0.0
 +            << 27 << 10 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple backwards, from visible -> non-visible")
 +            << 120.0     // show 6-23
 +            << 16 << 1 << 3
 +            << -60.0;   // to minimize movement, items are added above visible area, all items move up by 1 row
 +
 +    QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
 +            << 120.0     // show 6-23
 +            << 16 << 0 << 3
 +            << -60.0;   // 16,17,18 move to above item 0, all items move up by 1 row
 +}
 +
 +void tst_QQuickGridView::multipleChanges()
 +{
++    QSKIP("QTBUG-24523");
++
 +    QFETCH(int, startCount);
 +    QFETCH(QList<ListChange>, changes);
 +    QFETCH(int, newCount);
 +    QFETCH(int, newCurrentIndex);
 +
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < startCount; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    for (int i=0; i<changes.count(); i++) {
 +        switch (changes[i].type) {
 +            case ListChange::Inserted:
 +            {
 +                QList<QPair<QString, QString> > items;
 +                for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
 +                    items << qMakePair(QString("new item " + j), QString::number(j));
 +                model.insertItems(changes[i].index, items);
 +                break;
 +            }
 +            case ListChange::Removed:
 +                model.removeItems(changes[i].index, changes[i].count);
 +                QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +                break;
 +            case ListChange::Moved:
 +                model.moveItems(changes[i].index, changes[i].to, changes[i].count);
 +                QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +                break;
 +            case ListChange::SetCurrent:
 +                gridview->setCurrentIndex(changes[i].index);
 +                QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +                break;
 +            case ListChange::SetContentY:
 +                gridview->setContentY(changes[i].pos);
 +                QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +                break;
 +        }
 +    }
 +
 +    QTRY_COMPARE(gridview->count(), newCount);
 +    QCOMPARE(gridview->count(), model.count());
 +    QTRY_COMPARE(gridview->currentIndex(), newCurrentIndex);
 +
 +    QQuickText *name;
 +    QQuickText *number;
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i=0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QVERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::multipleChanges_data()
 +{
 +    QTest::addColumn<int>("startCount");
 +    QTest::addColumn<QList<ListChange> >("changes");
 +    QTest::addColumn<int>("newCount");
 +    QTest::addColumn<int>("newCurrentIndex");
 +
 +    QList<ListChange> changes;
 +
 +    for (int i=1; i<30; i++)
 +        changes << ListChange::remove(0);
 +    QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
 +
 +    changes << ListChange::remove(0);
 +    QTest::newRow("remove all") << 30 << changes << 0 << -1;
 +
 +    changes.clear();
 +    changes << ListChange::setCurrent(29);
 +    for (int i=29; i>0; i--)
 +        changes << ListChange::remove(i);
 +    QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
 +
 +    QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
 +            << ListChange::remove(0, 1)
 +            << ListChange::insert(0, 1)
 +            ) << 10 << 1;
 +
 +    QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(2)
 +            << ListChange::remove(2, 1)
 +            << ListChange::insert(2, 1)
 +            ) << 10 << 3;
 +
 +    QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(1)
 +            << ListChange::remove(1, 3)
 +            << ListChange::insert(2, 2)
 +            ) << 9 << 1;
 +
 +    QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(2)
 +            << ListChange::remove(1, 3)
 +            << ListChange::move(1, 5, 1)
 +            ) << 7 << 5;
 +
 +    QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(5)
 +            << ListChange::remove(4, 3)
 +            << ListChange::move(4, 1, 1)
 +            ) << 7 << 1;
 +
 +
 +    QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
 +            << ListChange::insert(0, 2)
 +            << ListChange::insert(0, 4)
 +            << ListChange::insert(0, 6)
 +            ) << 12 << 10;
 +
 +    QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
 +            << ListChange::insert(0, 2)
 +            << ListChange::insert(0, 4)
 +            << ListChange::insert(0, 6)
 +            << ListChange::setCurrent(3)
 +            << ListChange::insert(3, 2)
 +            ) << 14 << 5;
 +
 +    QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
 +            << ListChange::insert(0, 30)
 +            << ListChange::remove(0, 30)
 +            ) << 0 << -1;
 +
 +    QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
 +            << ListChange::insert(1)
 +            << ListChange::setCurrent(1)
 +            << ListChange::remove(1)
 +            ) << 30 << 1;
 +
 +    QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
 +            << ListChange::insert(0, 10)
 +            << ListChange::remove(5, 10)
 +            ) << 10 << 5;
 +
 +    QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
 +            << ListChange::insert(0, 3)
 +            << ListChange::move(0, 10, 3)
 +            ) << 13 << 0;
 +
 +    QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
 +            << ListChange::insert(0, 3)
 +            << ListChange::move(0, 8, 5)
 +            ) << 13 << 11;
 +
 +    QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(9)
 +            << ListChange::insert(10, 3)
 +            << ListChange::move(8, 0, 5)
 +            ) << 13 << 1;
 +
 +
 +    QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(1)
 +            << ListChange::move(1, 2, 2)
 +            << ListChange::move(2, 1, 2)
 +            ) << 10 << 1;
 +
 +    QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(2)
 +            << ListChange::move(1, 2, 3)
 +            << ListChange::move(3, 0, 5)
 +            ) << 10 << 0;
 +
 +    QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(5)
 +            << ListChange::move(5, 0, 1)
 +            << ListChange::remove(0)
 +            ) << 9 << 0;
 +
 +    QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(5)
 +            << ListChange::move(5, 0, 1)
 +            << ListChange::insert(0)
 +            ) << 11 << 1;
 +
 +    QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(1)
 +            << ListChange::move(5, 1, 3)
 +            << ListChange::remove(1, 3)
 +            ) << 7 << 1;
 +
 +    QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(5)
 +            << ListChange::move(5, 1, 3)
 +            << ListChange::insert(1, 5)
 +            ) << 15 << 6;
 +
 +    QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(3)
 +            << ListChange::move(0, 1, 2)
 +            << ListChange::insert(3, 5)
 +            ) << 15 << 8;
 +
 +
 +    QTest::newRow("clear current") << 0 << (QList<ListChange>()
 +            << ListChange::insert(0, 5)
 +            << ListChange::setCurrent(-1)
 +            << ListChange::remove(0, 5)
 +            << ListChange::insert(0, 5)
 +            ) << 5 << -1;
 +}
 +
 +
 +void tst_QQuickGridView::swapWithFirstItem()
 +{
 +    // QTBUG_9697
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    // ensure content position is stable
 +    gridview->setContentY(0);
 +    model.moveItem(10, 0);
 +    QTRY_VERIFY(gridview->contentY() == 0);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::currentIndex()
 +{
 +    QaimModel model;
 +    for (int i = 0; i < 60; i++)
 +        model.addItem("Item" + QString::number(i), QString::number(i));
 +
 +    QQuickView *canvas = new QQuickView(0);
 +    canvas->setGeometry(0,0,240,320);
 +    canvas->show();
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    QString filename(testFile("gridview-initCurrent.qml"));
 +    canvas->setSource(QUrl::fromLocalFile(filename));
 +
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QVERIFY(gridview != 0);
 +    QTRY_VERIFY(!QQuickItemPrivate::get(gridview)->polishScheduled);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem != 0);
 +
 +    // current item should be third item
 +    QCOMPARE(gridview->currentIndex(), 35);
 +    QCOMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 35));
 +    QCOMPARE(gridview->currentItem()->y(), gridview->highlightItem()->y());
 +    QCOMPARE(gridview->contentY(), 400.0);
 +
 +    gridview->moveCurrentIndexRight();
 +    QCOMPARE(gridview->currentIndex(), 36);
 +    gridview->moveCurrentIndexDown();
 +    QCOMPARE(gridview->currentIndex(), 39);
 +    gridview->moveCurrentIndexUp();
 +    QCOMPARE(gridview->currentIndex(), 36);
 +    gridview->moveCurrentIndexLeft();
 +    QCOMPARE(gridview->currentIndex(), 35);
 +
 +    // wait until motion stops
 +    QTRY_VERIFY(gridview->verticalVelocity() == 0.0);
 +
 +    // no wrap
 +    gridview->setCurrentIndex(0);
 +    QCOMPARE(gridview->currentIndex(), 0);
 +    // confirm that the velocity is updated
 +    QTRY_VERIFY(gridview->verticalVelocity() != 0.0);
 +
 +    gridview->moveCurrentIndexUp();
 +    QCOMPARE(gridview->currentIndex(), 0);
 +
 +    gridview->moveCurrentIndexLeft();
 +    QCOMPARE(gridview->currentIndex(), 0);
 +
 +    gridview->setCurrentIndex(model.count()-1);
 +    QCOMPARE(gridview->currentIndex(), model.count()-1);
 +
 +    gridview->moveCurrentIndexRight();
 +    QCOMPARE(gridview->currentIndex(), model.count()-1);
 +
 +    gridview->moveCurrentIndexDown();
 +    QCOMPARE(gridview->currentIndex(), model.count()-1);
 +
 +    // with wrap
 +    gridview->setWrapEnabled(true);
 +
 +    gridview->setCurrentIndex(0);
 +    QCOMPARE(gridview->currentIndex(), 0);
 +
 +    gridview->moveCurrentIndexLeft();
 +    QCOMPARE(gridview->currentIndex(), model.count()-1);
 +
 +    qApp->processEvents();
 +    QTRY_COMPARE(gridview->contentY(), 880.0);
 +
 +    gridview->moveCurrentIndexRight();
 +    QCOMPARE(gridview->currentIndex(), 0);
 +
 +    QTRY_COMPARE(gridview->contentY(), 0.0);
 +
 +
 +    // footer should become visible if it is out of view, and then current index moves to the first row
 +    canvas->rootObject()->setProperty("showFooter", true);
 +    QTRY_VERIFY(gridview->footerItem());
 +    gridview->setCurrentIndex(model.count()-3);
 +    QTRY_VERIFY(gridview->footerItem()->y() > gridview->contentY() + gridview->height());
 +    gridview->setCurrentIndex(model.count()-2);
 +    QTRY_COMPARE(gridview->contentY() + gridview->height(), (60.0 * model.count()/3) + gridview->footerItem()->height());
 +    canvas->rootObject()->setProperty("showFooter", false);
 +
 +    // header should become visible if it is out of view, and then current index moves to the last row
 +    canvas->rootObject()->setProperty("showHeader", true);
 +    QTRY_VERIFY(gridview->headerItem());
 +    gridview->setCurrentIndex(3);
 +    QTRY_VERIFY(gridview->headerItem()->y() + gridview->headerItem()->height() < gridview->contentY());
 +    gridview->setCurrentIndex(1);
 +    QTRY_COMPARE(gridview->contentY(), -gridview->headerItem()->height());
 +    canvas->rootObject()->setProperty("showHeader", false);
 +
 +
 +    // Test keys
 +    canvas->requestActivateWindow();
 +    QTest::qWaitForWindowShown(canvas);
 +    QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
 +
 +    gridview->setCurrentIndex(0);
 +
 +    QTest::keyClick(canvas, Qt::Key_Down);
 +    QCOMPARE(gridview->currentIndex(), 3);
 +
 +    QTest::keyClick(canvas, Qt::Key_Up);
 +    QCOMPARE(gridview->currentIndex(), 0);
 +
 +    // hold down Key_Down
 +    for (int i=0; i<(model.count() / 3) - 1; i++) {
 +        QTest::simulateEvent(canvas, true, Qt::Key_Down, Qt::NoModifier, "", true);
 +        QTRY_COMPARE(gridview->currentIndex(), i*3 + 3);
 +    }
 +    QTest::keyRelease(canvas, Qt::Key_Down);
 +    QTRY_COMPARE(gridview->currentIndex(), 57);
 +    QTRY_COMPARE(gridview->contentY(), 880.0);
 +
 +    // hold down Key_Up
 +    for (int i=(model.count() / 3) - 1; i > 0; i--) {
 +        QTest::simulateEvent(canvas, true, Qt::Key_Up, Qt::NoModifier, "", true);
 +        QTRY_COMPARE(gridview->currentIndex(), i*3 - 3);
 +    }
 +    QTest::keyRelease(canvas, Qt::Key_Up);
 +    QTRY_COMPARE(gridview->currentIndex(), 0);
 +    QTRY_COMPARE(gridview->contentY(), 0.0);
 +
 +
 +    gridview->setFlow(QQuickGridView::TopToBottom);
 +
 +    canvas->requestActivateWindow();
 +    QTest::qWaitForWindowShown(canvas);
 +    QVERIFY(qGuiApp->focusWindow() == canvas);
 +    qApp->processEvents();
 +
 +    QTest::keyClick(canvas, Qt::Key_Right);
 +    QCOMPARE(gridview->currentIndex(), 5);
 +
 +    QTest::keyClick(canvas, Qt::Key_Left);
 +    QCOMPARE(gridview->currentIndex(), 0);
 +
 +    QTest::keyClick(canvas, Qt::Key_Down);
 +    QCOMPARE(gridview->currentIndex(), 1);
 +
 +    QTest::keyClick(canvas, Qt::Key_Up);
 +    QCOMPARE(gridview->currentIndex(), 0);
 +
 +    // hold down Key_Right
 +    for (int i=0; i<(model.count() / 5) - 1; i++) {
 +        QTest::simulateEvent(canvas, true, Qt::Key_Right, Qt::NoModifier, "", true);
 +        QTRY_COMPARE(gridview->currentIndex(), i*5 + 5);
 +    }
 +
 +    QTest::keyRelease(canvas, Qt::Key_Right);
 +    QTRY_COMPARE(gridview->currentIndex(), 55);
 +    QTRY_COMPARE(gridview->contentX(), 720.0);
 +
 +    // hold down Key_Left
 +    for (int i=(model.count() / 5) - 1; i > 0; i--) {
 +        QTest::simulateEvent(canvas, true, Qt::Key_Left, Qt::NoModifier, "", true);
 +        QTRY_COMPARE(gridview->currentIndex(), i*5 - 5);
 +    }
 +    QTest::keyRelease(canvas, Qt::Key_Left);
 +    QTRY_COMPARE(gridview->currentIndex(), 0);
 +    QTRY_COMPARE(gridview->contentX(), 0.0);
 +
 +
 +    // turn off auto highlight
 +    gridview->setHighlightFollowsCurrentItem(false);
 +    QVERIFY(gridview->highlightFollowsCurrentItem() == false);
 +    QVERIFY(gridview->highlightItem());
 +    qreal hlPosX = gridview->highlightItem()->x();
 +    qreal hlPosY = gridview->highlightItem()->y();
 +
 +    gridview->setCurrentIndex(5);
 +    QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
 +    QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
 +
 +    // insert item before currentIndex
 +    gridview->setCurrentIndex(28);
 +    model.insertItem(0, "Foo", "1111");
 +    QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
 +
 +    // check removing highlight by setting currentIndex to -1;
 +    gridview->setCurrentIndex(-1);
 +
 +    QCOMPARE(gridview->currentIndex(), -1);
 +    QVERIFY(!gridview->highlightItem());
 +    QVERIFY(!gridview->currentItem());
 +
 +    gridview->setHighlightFollowsCurrentItem(true);
 +
 +    gridview->setFlow(QQuickGridView::LeftToRight);
 +    gridview->setLayoutDirection(Qt::RightToLeft);
 +
 +    canvas->requestActivateWindow();
 +    QTest::qWaitForWindowShown(canvas);
 +    QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
 +    qApp->processEvents();
 +
 +    gridview->setCurrentIndex(35);
 +
 +    QTest::keyClick(canvas, Qt::Key_Right);
 +    QCOMPARE(gridview->currentIndex(), 34);
 +
 +    QTest::keyClick(canvas, Qt::Key_Down);
 +    QCOMPARE(gridview->currentIndex(), 37);
 +
 +    QTest::keyClick(canvas, Qt::Key_Up);
 +    QCOMPARE(gridview->currentIndex(), 34);
 +
 +    QTest::keyClick(canvas, Qt::Key_Left);
 +    QCOMPARE(gridview->currentIndex(), 35);
 +
 +
 +    // turn off auto highlight
 +    gridview->setHighlightFollowsCurrentItem(false);
 +    QVERIFY(gridview->highlightFollowsCurrentItem() == false);
 +    QVERIFY(gridview->highlightItem());
 +    hlPosX = gridview->highlightItem()->x();
 +    hlPosY = gridview->highlightItem()->y();
 +
 +    gridview->setCurrentIndex(5);
 +    QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
 +    QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
 +
 +    // insert item before currentIndex
 +    gridview->setCurrentIndex(28);
 +    model.insertItem(0, "Foo", "1111");
 +    QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
 +
 +    // check removing highlight by setting currentIndex to -1;
 +    gridview->setCurrentIndex(-1);
 +
 +    QCOMPARE(gridview->currentIndex(), -1);
 +    QVERIFY(!gridview->highlightItem());
 +    QVERIFY(!gridview->currentItem());
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::noCurrentIndex()
 +{
 +    QaimModel model;
 +    for (int i = 0; i < 60; i++)
 +        model.addItem("Item" + QString::number(i), QString::number(i));
 +
 +    QQuickView *canvas = new QQuickView(0);
 +    canvas->setGeometry(0,0,240,320);
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    QString filename(testFile("gridview-noCurrent.qml"));
 +    canvas->setSource(QUrl::fromLocalFile(filename));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QVERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    // current index should be -1
 +    QCOMPARE(gridview->currentIndex(), -1);
 +    QVERIFY(!gridview->currentItem());
 +    QVERIFY(!gridview->highlightItem());
 +    QCOMPARE(gridview->contentY(), 0.0);
 +
 +    gridview->setCurrentIndex(5);
 +    QCOMPARE(gridview->currentIndex(), 5);
 +    QVERIFY(gridview->currentItem());
 +    QVERIFY(gridview->highlightItem());
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::changeFlow()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), QString::number(i));
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    // Confirm items positioned correctly and indexes correct
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal((i%3)*80));
 +        QTRY_COMPARE(item->y(), qreal((i/3)*60));
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QTRY_VERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QTRY_VERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +
 +    ctxt->setContextProperty("testTopToBottom", QVariant(true));
 +
 +    // Confirm items positioned correctly and indexes correct
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal((i/5)*80));
 +        QTRY_COMPARE(item->y(), qreal((i%5)*60));
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QTRY_VERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QTRY_VERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +
 +    ctxt->setContextProperty("testRightToLeft", QVariant(true));
 +
 +    // Confirm items positioned correctly and indexes correct
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal(-(i/5)*80 - item->width()));
 +        QTRY_COMPARE(item->y(), qreal((i%5)*60));
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QTRY_VERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QTRY_VERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +    gridview->setContentX(100);
 +    QTRY_COMPARE(gridview->contentX(), 100.);
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +    QTRY_COMPARE(gridview->contentX(), 0.);
 +
 +    // Confirm items positioned correctly and indexes correct
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal(240 - (i%3+1)*80));
 +        QTRY_COMPARE(item->y(), qreal((i/3)*60));
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QTRY_VERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QTRY_VERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::defaultValues()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent c(&engine, testFileUrl("gridview3.qml"));
 +    QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
 +
 +    QTRY_VERIFY(obj != 0);
 +    QTRY_VERIFY(obj->model() == QVariant());
 +    QTRY_VERIFY(obj->delegate() == 0);
 +    QTRY_COMPARE(obj->currentIndex(), -1);
 +    QTRY_VERIFY(obj->currentItem() == 0);
 +    QTRY_COMPARE(obj->count(), 0);
 +    QTRY_VERIFY(obj->highlight() == 0);
 +    QTRY_VERIFY(obj->highlightItem() == 0);
 +    QTRY_COMPARE(obj->highlightFollowsCurrentItem(), true);
 +    QTRY_VERIFY(obj->flow() == 0);
 +    QTRY_COMPARE(obj->isWrapEnabled(), false);
 +    QTRY_COMPARE(obj->cacheBuffer(), 0);
 +    QTRY_COMPARE(obj->cellWidth(), qreal(100)); //### Should 100 be the default?
 +    QTRY_COMPARE(obj->cellHeight(), qreal(100));
 +    delete obj;
 +}
 +
 +void tst_QQuickGridView::properties()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent c(&engine, testFileUrl("gridview2.qml"));
 +    QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
 +
 +    QTRY_VERIFY(obj != 0);
 +    QTRY_VERIFY(obj->model() != QVariant());
 +    QTRY_VERIFY(obj->delegate() != 0);
 +    QTRY_COMPARE(obj->currentIndex(), 0);
 +    QTRY_VERIFY(obj->currentItem() != 0);
 +    QTRY_COMPARE(obj->count(), 4);
 +    QTRY_VERIFY(obj->highlight() != 0);
 +    QTRY_VERIFY(obj->highlightItem() != 0);
 +    QTRY_COMPARE(obj->highlightFollowsCurrentItem(), false);
 +    QTRY_VERIFY(obj->flow() == 0);
 +    QTRY_COMPARE(obj->isWrapEnabled(), true);
 +    QTRY_COMPARE(obj->cacheBuffer(), 200);
 +    QTRY_COMPARE(obj->cellWidth(), qreal(100));
 +    QTRY_COMPARE(obj->cellHeight(), qreal(100));
 +    delete obj;
 +}
 +
 +void tst_QQuickGridView::propertyChanges()
 +{
 +    QQuickView *canvas = createView();
 +    QTRY_VERIFY(canvas);
 +    canvas->setSource(testFileUrl("propertychangestest.qml"));
 +
 +    QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
 +    QTRY_VERIFY(gridView);
 +
 +    QSignalSpy keyNavigationWrapsSpy(gridView, SIGNAL(keyNavigationWrapsChanged()));
 +    QSignalSpy cacheBufferSpy(gridView, SIGNAL(cacheBufferChanged()));
 +    QSignalSpy layoutSpy(gridView, SIGNAL(layoutDirectionChanged()));
 +    QSignalSpy flowSpy(gridView, SIGNAL(flowChanged()));
 +
 +    QTRY_COMPARE(gridView->isWrapEnabled(), true);
 +    QTRY_COMPARE(gridView->cacheBuffer(), 10);
 +    QTRY_COMPARE(gridView->flow(), QQuickGridView::LeftToRight);
 +
 +    gridView->setWrapEnabled(false);
 +    gridView->setCacheBuffer(3);
 +    gridView->setFlow(QQuickGridView::TopToBottom);
 +
 +    QTRY_COMPARE(gridView->isWrapEnabled(), false);
 +    QTRY_COMPARE(gridView->cacheBuffer(), 3);
 +    QTRY_COMPARE(gridView->flow(), QQuickGridView::TopToBottom);
 +
 +    QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
 +    QTRY_COMPARE(cacheBufferSpy.count(),1);
 +    QTRY_COMPARE(flowSpy.count(),1);
 +
 +    gridView->setWrapEnabled(false);
 +    gridView->setCacheBuffer(3);
 +    gridView->setFlow(QQuickGridView::TopToBottom);
 +
 +    QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
 +    QTRY_COMPARE(cacheBufferSpy.count(),1);
 +    QTRY_COMPARE(flowSpy.count(),1);
 +
 +    gridView->setFlow(QQuickGridView::LeftToRight);
 +    QTRY_COMPARE(gridView->flow(), QQuickGridView::LeftToRight);
 +
 +    gridView->setWrapEnabled(true);
 +    gridView->setCacheBuffer(5);
 +    gridView->setLayoutDirection(Qt::RightToLeft);
 +
 +    QTRY_COMPARE(gridView->isWrapEnabled(), true);
 +    QTRY_COMPARE(gridView->cacheBuffer(), 5);
 +    QTRY_COMPARE(gridView->layoutDirection(), Qt::RightToLeft);
 +
 +    QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
 +    QTRY_COMPARE(cacheBufferSpy.count(),2);
 +    QTRY_COMPARE(layoutSpy.count(),1);
 +    QTRY_COMPARE(flowSpy.count(),2);
 +
 +    gridView->setWrapEnabled(true);
 +    gridView->setCacheBuffer(5);
 +    gridView->setLayoutDirection(Qt::RightToLeft);
 +
 +    QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
 +    QTRY_COMPARE(cacheBufferSpy.count(),2);
 +    QTRY_COMPARE(layoutSpy.count(),1);
 +    QTRY_COMPARE(flowSpy.count(),2);
 +
 +    gridView->setFlow(QQuickGridView::TopToBottom);
 +    QTRY_COMPARE(gridView->flow(), QQuickGridView::TopToBottom);
 +    QTRY_COMPARE(flowSpy.count(),3);
 +
 +    gridView->setFlow(QQuickGridView::TopToBottom);
 +    QTRY_COMPARE(flowSpy.count(),3);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::componentChanges()
 +{
 +    QQuickView *canvas = createView();
 +    QTRY_VERIFY(canvas);
 +    canvas->setSource(testFileUrl("propertychangestest.qml"));
 +
 +    QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
 +    QTRY_VERIFY(gridView);
 +
 +    QQmlComponent component(canvas->engine());
-     delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
++    component.setData("import QtQuick 1.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
 +
 +    QQmlComponent delegateComponent(canvas->engine());
-             << ListChange::insert(0, 1)
-             << ListChange::move(0, 3, 1)
-             );
++    delegateComponent.setData("import QtQuick 1.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
 +
 +    QSignalSpy highlightSpy(gridView, SIGNAL(highlightChanged()));
 +    QSignalSpy delegateSpy(gridView, SIGNAL(delegateChanged()));
 +    QSignalSpy headerSpy(gridView, SIGNAL(headerChanged()));
 +    QSignalSpy footerSpy(gridView, SIGNAL(footerChanged()));
 +
 +    gridView->setHighlight(&component);
 +    gridView->setDelegate(&delegateComponent);
 +    gridView->setHeader(&component);
 +    gridView->setFooter(&component);
 +
 +    QTRY_COMPARE(gridView->highlight(), &component);
 +    QTRY_COMPARE(gridView->delegate(), &delegateComponent);
 +    QTRY_COMPARE(gridView->header(), &component);
 +    QTRY_COMPARE(gridView->footer(), &component);
 +
 +    QTRY_COMPARE(highlightSpy.count(),1);
 +    QTRY_COMPARE(delegateSpy.count(),1);
 +    QTRY_COMPARE(headerSpy.count(),1);
 +    QTRY_COMPARE(footerSpy.count(),1);
 +
 +    gridView->setHighlight(&component);
 +    gridView->setDelegate(&delegateComponent);
 +    gridView->setHeader(&component);
 +    gridView->setFooter(&component);
 +
 +    QTRY_COMPARE(highlightSpy.count(),1);
 +    QTRY_COMPARE(delegateSpy.count(),1);
 +    QTRY_COMPARE(headerSpy.count(),1);
 +    QTRY_COMPARE(footerSpy.count(),1);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::modelChanges()
 +{
 +    QQuickView *canvas = createView();
 +    QTRY_VERIFY(canvas);
 +    canvas->setSource(testFileUrl("propertychangestest.qml"));
 +
 +    QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
 +    QTRY_VERIFY(gridView);
 +
 +    QQuickListModel *alternateModel = canvas->rootObject()->findChild<QQuickListModel*>("alternateModel");
 +    QTRY_VERIFY(alternateModel);
 +    QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
 +    QSignalSpy modelSpy(gridView, SIGNAL(modelChanged()));
 +
 +    gridView->setModel(modelVariant);
 +    QTRY_COMPARE(gridView->model(), modelVariant);
 +    QTRY_COMPARE(modelSpy.count(),1);
 +
 +    gridView->setModel(modelVariant);
 +    QTRY_COMPARE(modelSpy.count(),1);
 +
 +    gridView->setModel(QVariant());
 +    QTRY_COMPARE(modelSpy.count(),2);
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::positionViewAtIndex()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 40; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), (i%3)*80.);
 +        QTRY_COMPARE(item->y(), (i/3)*60.);
 +    }
 +
 +    // Position on a currently visible item
 +    gridview->positionViewAtIndex(4, QQuickGridView::Beginning);
 +    QTRY_COMPARE(gridview->indexAt(120, 90), 4);
 +    QTRY_COMPARE(gridview->contentY(), 60.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), (i%3)*80.);
 +        QTRY_COMPARE(item->y(), (i/3)*60.);
 +    }
 +
 +    // Position on an item beyond the visible items
 +    gridview->positionViewAtIndex(21, QQuickGridView::Beginning);
 +    QTRY_COMPARE(gridview->indexAt(40, 450), 21);
 +    QTRY_COMPARE(gridview->contentY(), 420.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), (i%3)*80.);
 +        QTRY_COMPARE(item->y(), (i/3)*60.);
 +    }
 +
 +    // Position on an item that would leave empty space if positioned at the top
 +    gridview->positionViewAtIndex(31, QQuickGridView::Beginning);
 +    QTRY_COMPARE(gridview->indexAt(120, 630), 31);
 +    QTRY_COMPARE(gridview->contentY(), 520.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), (i%3)*80.);
 +        QTRY_COMPARE(item->y(), (i/3)*60.);
 +    }
 +
 +    // Position at the beginning again
 +    gridview->positionViewAtIndex(0, QQuickGridView::Beginning);
 +    QTRY_COMPARE(gridview->indexAt(0, 0), 0);
 +    QTRY_COMPARE(gridview->indexAt(40, 30), 0);
 +    QTRY_COMPARE(gridview->indexAt(80, 60), 4);
 +    QTRY_COMPARE(gridview->contentY(), 0.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), (i%3)*80.);
 +        QTRY_COMPARE(item->y(), (i/3)*60.);
 +    }
 +
 +    // Position at End
 +    gridview->positionViewAtIndex(30, QQuickGridView::End);
 +    QTRY_COMPARE(gridview->contentY(), 340.);
 +
 +    // Position in Center
 +    gridview->positionViewAtIndex(15, QQuickGridView::Center);
 +    QTRY_COMPARE(gridview->contentY(), 170.);
 +
 +    // Ensure at least partially visible
 +    gridview->positionViewAtIndex(15, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentY(), 170.);
 +
 +    gridview->setContentY(302);
 +    gridview->positionViewAtIndex(15, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentY(), 302.);
 +
 +    gridview->setContentY(360);
 +    gridview->positionViewAtIndex(15, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentY(), 300.);
 +
 +    gridview->setContentY(60);
 +    gridview->positionViewAtIndex(20, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentY(), 60.);
 +
 +    gridview->setContentY(20);
 +    gridview->positionViewAtIndex(20, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentY(), 100.);
 +
 +    // Ensure completely visible
 +    gridview->setContentY(120);
 +    gridview->positionViewAtIndex(20, QQuickGridView::Contain);
 +    QTRY_COMPARE(gridview->contentY(), 120.);
 +
 +    gridview->setContentY(302);
 +    gridview->positionViewAtIndex(15, QQuickGridView::Contain);
 +    QTRY_COMPARE(gridview->contentY(), 300.);
 +
 +    gridview->setContentY(60);
 +    gridview->positionViewAtIndex(20, QQuickGridView::Contain);
 +    QTRY_COMPARE(gridview->contentY(), 100.);
 +
 +    // Test for Top To Bottom layout
 +    ctxt->setContextProperty("testTopToBottom", QVariant(true));
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), (i/5)*80.);
 +        QTRY_COMPARE(item->y(), (i%5)*60.);
 +    }
 +
 +    // Position at End
 +    gridview->positionViewAtIndex(30, QQuickGridView::End);
 +    QTRY_COMPARE(gridview->contentX(), 320.);
 +    QTRY_COMPARE(gridview->contentY(), 0.);
 +
 +    // Position in Center
 +    gridview->positionViewAtIndex(15, QQuickGridView::Center);
 +    QTRY_COMPARE(gridview->contentX(), 160.);
 +
 +    // Ensure at least partially visible
 +    gridview->positionViewAtIndex(15, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentX(), 160.);
 +
 +    gridview->setContentX(170);
 +    gridview->positionViewAtIndex(25, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentX(), 170.);
 +
 +    gridview->positionViewAtIndex(30, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentX(), 320.);
 +
 +    gridview->setContentX(170);
 +    gridview->positionViewAtIndex(25, QQuickGridView::Contain);
 +    QTRY_COMPARE(gridview->contentX(), 240.);
 +
 +    // positionViewAtBeginning
 +    gridview->positionViewAtBeginning();
 +    QTRY_COMPARE(gridview->contentX(), 0.);
 +
 +    gridview->setContentX(80);
 +    canvas->rootObject()->setProperty("showHeader", true);
 +    gridview->positionViewAtBeginning();
 +    QTRY_COMPARE(gridview->contentX(), -30.);
 +
 +    // positionViewAtEnd
 +    gridview->positionViewAtEnd();
 +    QTRY_COMPARE(gridview->contentX(), 400.);   // 8*80 - 240   (8 columns)
 +
 +    gridview->setContentX(80);
 +    canvas->rootObject()->setProperty("showFooter", true);
 +    gridview->positionViewAtEnd();
 +    QTRY_COMPARE(gridview->contentX(), 430.);
 +
 +    // set current item to outside visible view, position at beginning
 +    // and ensure highlight moves to current item
 +    gridview->setCurrentIndex(6);
 +    gridview->positionViewAtBeginning();
 +    QTRY_COMPARE(gridview->contentX(), -30.);
 +    QVERIFY(gridview->highlightItem());
 +    QCOMPARE(gridview->highlightItem()->x(), 80.);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::snapping()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 40; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    gridview->setHeight(220);
 +    QCOMPARE(gridview->height(), 220.);
 +
 +    gridview->positionViewAtIndex(12, QQuickGridView::Visible);
 +    QCOMPARE(gridview->contentY(), 80.);
 +
 +    gridview->setContentY(0);
 +    QCOMPARE(gridview->contentY(), 0.);
 +
 +    gridview->setSnapMode(QQuickGridView::SnapToRow);
 +    QCOMPARE(gridview->snapMode(), QQuickGridView::SnapToRow);
 +
 +    gridview->positionViewAtIndex(12, QQuickGridView::Visible);
 +    QCOMPARE(gridview->contentY(), 60.);
 +
 +    gridview->positionViewAtIndex(15, QQuickGridView::End);
 +    QCOMPARE(gridview->contentY(), 120.);
 +
 +    delete canvas;
 +
 +}
 +
 +void tst_QQuickGridView::mirroring()
 +{
 +    QQuickView *canvasA = createView();
 +    canvasA->setSource(testFileUrl("mirroring.qml"));
 +    QQuickGridView *gridviewA = findItem<QQuickGridView>(canvasA->rootObject(), "view");
 +    QTRY_VERIFY(gridviewA != 0);
 +
 +    QQuickView *canvasB = createView();
 +    canvasB->setSource(testFileUrl("mirroring.qml"));
 +    QQuickGridView *gridviewB = findItem<QQuickGridView>(canvasB->rootObject(), "view");
 +    QTRY_VERIFY(gridviewA != 0);
 +    qApp->processEvents();
 +
 +    QList<QString> objectNames;
 +    objectNames << "item1" << "item2"; // << "item3"
 +
 +    gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
 +    gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
 +    QCOMPARE(gridviewA->layoutDirection(), gridviewA->effectiveLayoutDirection());
 +
 +    // LTR != RTL
 +    foreach (const QString objectName, objectNames)
 +        QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
 +
 +    gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
 +    gridviewB->setProperty("layoutDirection", Qt::LeftToRight);
 +
 +    // LTR == LTR
 +    foreach (const QString objectName, objectNames)
 +        QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
 +
 +    QVERIFY(gridviewB->layoutDirection() == gridviewB->effectiveLayoutDirection());
 +    QQuickItemPrivate::get(gridviewB)->setLayoutMirror(true);
 +    QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection());
 +
 +    // LTR != LTR+mirror
 +    foreach (const QString objectName, objectNames)
 +        QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
 +
 +    gridviewA->setProperty("layoutDirection", Qt::RightToLeft);
 +
 +    // RTL == LTR+mirror
 +    foreach (const QString objectName, objectNames)
 +        QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
 +
 +    gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
 +
 +    // RTL != RTL+mirror
 +    foreach (const QString objectName, objectNames)
 +        QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
 +
 +    gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
 +
 +    // LTR == RTL+mirror
 +    foreach (const QString objectName, objectNames)
 +        QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
 +
 +    delete canvasA;
 +    delete canvasB;
 +}
 +
 +void tst_QQuickGridView::positionViewAtIndex_rightToLeft()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 40; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testTopToBottom", QVariant(true));
 +    ctxt->setContextProperty("testRightToLeft", QVariant(true));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
 +        QTRY_COMPARE(item->y(), qreal((i%5)*60));
 +    }
 +
 +    // Position on a currently visible item
 +    gridview->positionViewAtIndex(6, QQuickGridView::Beginning);
 +    QTRY_COMPARE(gridview->contentX(), -320.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
 +        QTRY_COMPARE(item->y(), qreal((i%5)*60));
 +    }
 +
 +    // Position on an item beyond the visible items
 +    gridview->positionViewAtIndex(21, QQuickGridView::Beginning);
 +    QTRY_COMPARE(gridview->contentX(), -560.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
 +        QTRY_COMPARE(item->y(), qreal((i%5)*60));
 +    }
 +
 +    // Position on an item that would leave empty space if positioned at the top
 +    gridview->positionViewAtIndex(31, QQuickGridView::Beginning);
 +    QTRY_COMPARE(gridview->contentX(), -640.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
 +        QTRY_COMPARE(item->y(), qreal((i%5)*60));
 +    }
 +
 +    // Position at the beginning again
 +    gridview->positionViewAtIndex(0, QQuickGridView::Beginning);
 +    QTRY_COMPARE(gridview->contentX(), -240.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
 +        QTRY_COMPARE(item->y(), qreal((i%5)*60));
 +    }
 +
 +    // Position at End
 +    gridview->positionViewAtIndex(30, QQuickGridView::End);
 +    QTRY_COMPARE(gridview->contentX(), -560.);
 +
 +    // Position in Center
 +    gridview->positionViewAtIndex(15, QQuickGridView::Center);
 +    QTRY_COMPARE(gridview->contentX(), -400.);
 +
 +    // Ensure at least partially visible
 +    gridview->positionViewAtIndex(15, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentX(), -400.);
 +
 +    gridview->setContentX(-555.);
 +    gridview->positionViewAtIndex(15, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentX(), -555.);
 +
 +    gridview->setContentX(-239);
 +    gridview->positionViewAtIndex(15, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentX(), -320.);
 +
 +    gridview->setContentX(-239);
 +    gridview->positionViewAtIndex(20, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentX(), -400.);
 +
 +    gridview->setContentX(-640);
 +    gridview->positionViewAtIndex(20, QQuickGridView::Visible);
 +    QTRY_COMPARE(gridview->contentX(), -560.);
 +
 +    // Ensure completely visible
 +    gridview->setContentX(-400);
 +    gridview->positionViewAtIndex(20, QQuickGridView::Contain);
 +    QTRY_COMPARE(gridview->contentX(), -400.);
 +
 +    gridview->setContentX(-315);
 +    gridview->positionViewAtIndex(15, QQuickGridView::Contain);
 +    QTRY_COMPARE(gridview->contentX(), -320.);
 +
 +    gridview->setContentX(-640);
 +    gridview->positionViewAtIndex(20, QQuickGridView::Contain);
 +    QTRY_COMPARE(gridview->contentX(), -560.);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::resetModel()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QStringList strings;
 +    strings << "one" << "two" << "three";
 +    QStringListModel model(strings);
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("displaygrid.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    QTRY_COMPARE(gridview->count(), model.rowCount());
 +
 +    for (int i = 0; i < model.rowCount(); ++i) {
 +        QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
 +        QTRY_VERIFY(display != 0);
 +        QTRY_COMPARE(display->text(), strings.at(i));
 +    }
 +
 +    strings.clear();
 +    strings << "four" << "five" << "six" << "seven";
 +    model.setStringList(strings);
 +
 +    QTRY_COMPARE(gridview->count(), model.rowCount());
 +
 +    for (int i = 0; i < model.rowCount(); ++i) {
 +        QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
 +        QTRY_VERIFY(display != 0);
 +        QTRY_COMPARE(display->text(), strings.at(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::enforceRange()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview-enforcerange.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +    QVERIFY(canvas->rootObject() != 0);
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0);
 +    QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0);
 +    QTRY_COMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    // view should be positioned at the top of the range.
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(gridview->contentY(), -100.0);
 +
 +    QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(0));
 +    QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(0));
 +
 +    // Check currentIndex is updated when contentItem moves
 +    gridview->setContentY(0);
 +    QTRY_COMPARE(gridview->currentIndex(), 2);
 +
 +    gridview->setCurrentIndex(5);
 +    QTRY_COMPARE(gridview->contentY(), 100.);
 +
 +    QaimModel model2;
 +    for (int i = 0; i < 5; i++)
 +        model2.addItem("Item" + QString::number(i), "");
 +
 +    ctxt->setContextProperty("testModel", &model2);
 +    QCOMPARE(gridview->count(), 5);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::enforceRange_rightToLeft()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(true));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(true));
 +
 +    canvas->setSource(testFileUrl("gridview-enforcerange.qml"));
 +    qApp->processEvents();
 +    QVERIFY(canvas->rootObject() != 0);
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    QCOMPARE(gridview->preferredHighlightBegin(), 100.0);
 +    QCOMPARE(gridview->preferredHighlightEnd(), 100.0);
 +    QCOMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem != 0);
 +
 +    // view should be positioned at the top of the range.
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item);
 +    QTRY_COMPARE(gridview->contentX(), -140.);
 +    QTRY_COMPARE(gridview->contentY(), 0.0);
 +
 +    QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(0));
 +    QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(0));
 +
 +    // Check currentIndex is updated when contentItem moves
 +    gridview->setContentX(-240);
 +    QTRY_COMPARE(gridview->currentIndex(), 3);
 +
 +    gridview->setCurrentIndex(7);
 +    QTRY_COMPARE(gridview->contentX(), -340.);
 +    QTRY_COMPARE(gridview->contentY(), 0.0);
 +
 +    QaimModel model2;
 +    for (int i = 0; i < 5; i++)
 +        model2.addItem("Item" + QString::number(i), "");
 +
 +    ctxt->setContextProperty("testModel", &model2);
 +    QCOMPARE(gridview->count(), 5);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::QTBUG_8456()
 +{
 +    QQuickView *canvas = createView();
 +
 +    canvas->setSource(testFileUrl("setindex.qml"));
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    QTRY_COMPARE(gridview->currentIndex(), 0);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::manualHighlight()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QString filename(testFile("manual-highlight.qml"));
 +    canvas->setSource(QUrl::fromLocalFile(filename));
 +
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QTRY_COMPARE(gridview->currentIndex(), 0);
 +    QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
 +    QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
 +    QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
 +
 +    gridview->setCurrentIndex(2);
 +
 +    QTRY_COMPARE(gridview->currentIndex(), 2);
 +    QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
 +    QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
 +    QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
 +
 +    gridview->positionViewAtIndex(8, QQuickGridView::Contain);
 +
 +    QTRY_COMPARE(gridview->currentIndex(), 2);
 +    QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
 +    QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
 +    QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
 +
 +    gridview->setFlow(QQuickGridView::TopToBottom);
 +    QTRY_COMPARE(gridview->flow(), QQuickGridView::TopToBottom);
 +
 +    gridview->setCurrentIndex(0);
 +    QTRY_COMPARE(gridview->currentIndex(), 0);
 +    QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
 +    QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
 +    QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
 +
 +    delete canvas;
 +}
 +
 +
 +void tst_QQuickGridView::footer()
 +{
 +    QFETCH(QQuickGridView::Flow, flow);
 +    QFETCH(Qt::LayoutDirection, layoutDirection);
 +    QFETCH(QPointF, initialFooterPos);
 +    QFETCH(QPointF, changedFooterPos);
 +    QFETCH(QPointF, initialContentPos);
 +    QFETCH(QPointF, changedContentPos);
 +    QFETCH(QPointF, firstDelegatePos);
 +    QFETCH(QPointF, resizeContentPos);
 +
 +    QQuickView *canvas = createView();
 +    canvas->show();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 7; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("footer.qml"));
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    gridview->setFlow(flow);
 +    gridview->setLayoutDirection(layoutDirection);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
 +    QVERIFY(footer);
 +
 +    QVERIFY(footer == gridview->footerItem());
 +
 +    QCOMPARE(footer->pos(), initialFooterPos);
 +    QCOMPARE(footer->width(), 100.);
 +    QCOMPARE(footer->height(), 30.);
 +    QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
 +
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item);
 +    QCOMPARE(item->pos(), firstDelegatePos);
 +
 +    if (flow == QQuickGridView::LeftToRight) {
 +        // shrink by one row
 +        model.removeItem(2);
 +        QTRY_COMPARE(footer->y(), initialFooterPos.y() - gridview->cellHeight());
 +    } else {
 +        // shrink by one column
 +        model.removeItem(2);
 +        model.removeItem(3);
 +        if (layoutDirection == Qt::LeftToRight)
 +            QTRY_COMPARE(footer->x(), initialFooterPos.x() - gridview->cellWidth());
 +        else
 +            QTRY_COMPARE(footer->x(), initialFooterPos.x() + gridview->cellWidth());
 +    }
 +
 +    // remove all items
 +    model.clear();
 +
 +    QPointF posWhenNoItems(0, 0);
 +    if (layoutDirection == Qt::RightToLeft)
 +        posWhenNoItems.setX(flow == QQuickGridView::LeftToRight ? gridview->width() - footer->width() : -footer->width());
 +    QTRY_COMPARE(footer->pos(), posWhenNoItems);
 +
 +    // if header is present, it's at a negative pos, so the footer should not move
 +    canvas->rootObject()->setProperty("showHeader", true);
 +    QVERIFY(findItem<QQuickItem>(contentItem, "header") != 0);
 +    QTRY_COMPARE(footer->pos(), posWhenNoItems);
 +    canvas->rootObject()->setProperty("showHeader", false);
 +
 +    // add 30 items
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QSignalSpy footerItemSpy(gridview, SIGNAL(footerItemChanged()));
 +    QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
 +
 +    QCOMPARE(footerItemSpy.count(), 1);
 +
 +    footer = findItem<QQuickText>(contentItem, "footer");
 +    QVERIFY(!footer);
 +    footer = findItem<QQuickText>(contentItem, "footer2");
 +    QVERIFY(footer);
 +
 +    QVERIFY(footer == gridview->footerItem());
 +
 +    QCOMPARE(footer->pos(), changedFooterPos);
 +    QCOMPARE(footer->width(), 50.);
 +    QCOMPARE(footer->height(), 20.);
 +    QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), changedContentPos);
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item);
 +    QCOMPARE(item->pos(), firstDelegatePos);
 +
 +    gridview->positionViewAtEnd();
 +    footer->setHeight(10);
 +    footer->setWidth(40);
 +    QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::footer_data()
 +{
 +    QTest::addColumn<QQuickGridView::Flow>("flow");
 +    QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
 +    QTest::addColumn<QPointF>("initialFooterPos");
 +    QTest::addColumn<QPointF>("changedFooterPos");
 +    QTest::addColumn<QPointF>("initialContentPos");
 +    QTest::addColumn<QPointF>("changedContentPos");
 +    QTest::addColumn<QPointF>("firstDelegatePos");
 +    QTest::addColumn<QPointF>("resizeContentPos");
 +
 +    // footer1 = 100 x 30
 +    // footer2 = 50 x 20
 +    // cells = 80 * 60
 +    // view width = 240
 +    // view height = 320
 +
 +    // footer below items, bottom left
 +    QTest::newRow("flow left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight
 +        << QPointF(0, 3 * 60)  // 180 = height of 3 rows (cell height is 60)
 +        << QPointF(0, 10 * 60)  // 30 items = 10 rows
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(0, 10 * 60 - 320 + 10);
 +
 +    // footer below items, bottom right
 +    QTest::newRow("flow left to right, layout right to left") << QQuickGridView::LeftToRight << Qt::RightToLeft
 +        << QPointF(240 - 100, 3 * 60)
 +        << QPointF((240 - 100) + 50, 10 * 60)     // 50 = width diff between old and new footers
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(240 - 80, 0)
 +        << QPointF(0, 10 * 60 - 320 + 10);
 +
 +    // footer to right of items
 +    QTest::newRow("flow top to bottom, layout left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight
 +        << QPointF(2 * 80, 0)      // 2 columns, cell width 80
 +        << QPointF(6 * 80, 0)      // 30 items = 6 columns
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(6 * 80 - 240 + 40, 0);
 +
 +    // footer to left of items
 +    QTest::newRow("flow top to bottom, layout right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft
 +        << QPointF(-(2 * 80) - 100, 0)
 +        << QPointF(-(6 * 80) - 50, 0)     // 50 = new footer width
 +        << QPointF(-240, 0)
 +        << QPointF(-240, 0)    // unchanged, footer change doesn't change content pos
 +        << QPointF(-80, 0)
 +        << QPointF(-(6 * 80) - 40, 0);
 +}
 +
 +void tst_QQuickGridView::header()
 +{
 +    QFETCH(QQuickGridView::Flow, flow);
 +    QFETCH(Qt::LayoutDirection, layoutDirection);
 +    QFETCH(QPointF, initialHeaderPos);
 +    QFETCH(QPointF, changedHeaderPos);
 +    QFETCH(QPointF, initialContentPos);
 +    QFETCH(QPointF, changedContentPos);
 +    QFETCH(QPointF, firstDelegatePos);
 +    QFETCH(QPointF, resizeContentPos);
 +
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQuickView *canvas = createView();
 +    canvas->rootContext()->setContextProperty("testModel", &model);
 +    canvas->rootContext()->setContextProperty("initialViewWidth", 240);
 +    canvas->rootContext()->setContextProperty("initialViewHeight", 320);
 +    canvas->setSource(testFileUrl("header.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    gridview->setFlow(flow);
 +    gridview->setLayoutDirection(layoutDirection);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QQuickText *header = findItem<QQuickText>(contentItem, "header");
 +    QVERIFY(header);
 +
 +    QVERIFY(header == gridview->headerItem());
 +
 +    QCOMPARE(header->pos(), initialHeaderPos);
 +    QCOMPARE(header->width(), 100.);
 +    QCOMPARE(header->height(), 30.);
 +    QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
 +
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item);
 +    QCOMPARE(item->pos(), firstDelegatePos);
 +
 +    model.clear();
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +    QCOMPARE(header->pos(), initialHeaderPos); // header should stay where it is
 +
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QSignalSpy headerItemSpy(gridview, SIGNAL(headerItemChanged()));
 +    QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
 +
 +    QCOMPARE(headerItemSpy.count(), 1);
 +
 +    header = findItem<QQuickText>(contentItem, "header");
 +    QVERIFY(!header);
 +    header = findItem<QQuickText>(contentItem, "header2");
 +    QVERIFY(header);
 +
 +    QVERIFY(header == gridview->headerItem());
 +
 +    QCOMPARE(header->pos(), changedHeaderPos);
 +    QCOMPARE(header->width(), 50.);
 +    QCOMPARE(header->height(), 20.);
 +    QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), changedContentPos);
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item);
 +    QCOMPARE(item->pos(), firstDelegatePos);
 +
 +    header->setHeight(10);
 +    header->setWidth(40);
 +    QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
 +
 +    delete canvas;
 +
 +
 +    // QTBUG-21207 header should become visible if view resizes from initial empty size
 +
 +    canvas = createView();
 +    canvas->rootContext()->setContextProperty("testModel", &model);
 +    canvas->rootContext()->setContextProperty("initialViewWidth", 240);
 +    canvas->rootContext()->setContextProperty("initialViewHeight", 320);
 +    canvas->setSource(testFileUrl("header.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    gridview->setFlow(flow);
 +    gridview->setLayoutDirection(layoutDirection);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    gridview->setWidth(240);
 +    gridview->setHeight(320);
 +    QTRY_COMPARE(gridview->headerItem()->pos(), initialHeaderPos);
 +    QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::header_data()
 +{
 +    QTest::addColumn<QQuickGridView::Flow>("flow");
 +    QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
 +    QTest::addColumn<QPointF>("initialHeaderPos");
 +    QTest::addColumn<QPointF>("changedHeaderPos");
 +    QTest::addColumn<QPointF>("initialContentPos");
 +    QTest::addColumn<QPointF>("changedContentPos");
 +    QTest::addColumn<QPointF>("firstDelegatePos");
 +    QTest::addColumn<QPointF>("resizeContentPos");
 +
 +    // header1 = 100 x 30
 +    // header2 = 50 x 20
 +    // cells = 80 x 60
 +    // view width = 240
 +
 +    // header above items, top left
 +    QTest::newRow("flow left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight
 +        << QPointF(0, -30)
 +        << QPointF(0, -20)
 +        << QPointF(0, -30)
 +        << QPointF(0, -20)
 +        << QPointF(0, 0)
 +        << QPointF(0, -10);
 +
 +    // header above items, top right
 +    QTest::newRow("flow left to right, layout right to left") << QQuickGridView::LeftToRight << Qt::RightToLeft
 +        << QPointF(240 - 100, -30)
 +        << QPointF((240 - 100) + 50, -20)     // 50 = width diff between old and new headers
 +        << QPointF(0, -30)
 +        << QPointF(0, -20)
 +        << QPointF(160, 0)
 +        << QPointF(0, -10);
 +
 +    // header to left of items
 +    QTest::newRow("flow top to bottom, layout left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight
 +        << QPointF(-100, 0)
 +        << QPointF(-50, 0)
 +        << QPointF(-100, 0)
 +        << QPointF(-50, 0)
 +        << QPointF(0, 0)
 +        << QPointF(-40, 0);
 +
 +    // header to right of items
 +    QTest::newRow("flow top to bottom, layout right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(-(240 - 100), 0)
 +        << QPointF(-(240 - 50), 0)
 +        << QPointF(-80, 0)
 +        << QPointF(-(240 - 40), 0);
 +}
 +
 +void tst_QQuickGridView::resizeViewAndRepaint()
 +{
 +    QQuickView *canvas = createView();
 +    canvas->show();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 40; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("initialWidth", 240);
 +    ctxt->setContextProperty("initialHeight", 100);
 +
 +    canvas->setSource(testFileUrl("resizeview.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    // item at index 10 should not be currently visible
 +    QVERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
 +
 +    gridview->setHeight(320);
 +    QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", 10));
 +
 +    gridview->setHeight(100);
 +    QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
 +
 +    // Ensure we handle -ve sizes
 +    gridview->setHeight(-100);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper", false).count(), 3);
 +
 +    gridview->setCacheBuffer(120);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper", false).count(), 9);
 +
 +    // ensure items in cache become visible
 +    gridview->setHeight(120);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper", false).count(), 15);
 +
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal((i%3)*80));
 +        QTRY_COMPARE(item->y(), qreal((i/3)*60));
 +        QCOMPARE(item->isVisible(), i < 9); // inside view visible, outside not visible
 +    }
 +
 +    // ensure items outside view become invisible
 +    gridview->setHeight(60);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper", false).count(), 12);
 +
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper", false).count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), qreal((i%3)*80));
 +        QTRY_COMPARE(item->y(), qreal((i/3)*60));
 +        QCOMPARE(item->isVisible(), i < 6); // inside view visible, outside not visible
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::changeColumnCount()
 +{
 +    QmlListModel model;
 +    for (int i = 0; i < 40; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("initialWidth", 100);
 +    ctxt->setContextProperty("initialHeight", 320);
 +    canvas->setSource(testFileUrl("resizeview.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    // a single column of 6 items are visible
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    QCOMPARE(itemCount, 6);
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), 0.0);
 +        QCOMPARE(item->y(), qreal(i*60));
 +    }
 +
 +    // now 6x3 grid is visible, plus 1 extra below for refill
 +    gridview->setWidth(240);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    QCOMPARE(itemCount, 6*3 + 1);
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), qreal((i%3)*80));
 +        QCOMPARE(item->y(), qreal((i/3)*60));
 +    }
 +
 +    // back to single column
 +    gridview->setWidth(100);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    QCOMPARE(itemCount, 6);
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), 0.0);
 +        QCOMPARE(item->y(), qreal(i*60));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::indexAt_itemAt_data()
 +{
 +    QTest::addColumn<qreal>("x");
 +    QTest::addColumn<qreal>("y");
 +    QTest::addColumn<int>("index");
 +
 +    QTest::newRow("Item 0 - 0, 0") << 0. << 0. << 0;
 +    QTest::newRow("Item 0 - 79, 59") << 79. << 59. << 0;
 +    QTest::newRow("Item 1 - 80, 0") << 80. << 0. << 1;
 +    QTest::newRow("Item 3 - 0, 60") << 0. << 60. << 3;
 +    QTest::newRow("No Item - 240, 0") << 240. << 0. << -1;
 +}
 +
 +void tst_QQuickGridView::indexAt_itemAt()
 +{
 +    QFETCH(qreal, x);
 +    QFETCH(qreal, y);
 +    QFETCH(int, index);
 +
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    model.addItem("Fred", "12345");
 +    model.addItem("John", "2345");
 +    model.addItem("Bob", "54321");
 +    model.addItem("Billy", "22345");
 +    model.addItem("Sam", "2945");
 +    model.addItem("Ben", "04321");
 +    model.addItem("Jim", "0780");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QTRY_COMPARE(gridview->count(), model.count());
 +
 +    QQuickItem *item = 0;
 +    if (index >= 0) {
 +        item = findItem<QQuickItem>(contentItem, "wrapper", index);
 +        QVERIFY(item);
 +    }
 +    QCOMPARE(gridview->indexAt(x, y), index);
 +    QVERIFY(gridview->itemAt(x, y) == item);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::onAdd()
 +{
 +    QFETCH(int, initialItemCount);
 +    QFETCH(int, itemsToAdd);
 +
 +    const int delegateWidth = 50;
 +    const int delegateHeight = 100;
 +    QaimModel model;
 +    QQuickView *canvas = createView();
 +    canvas->setGeometry(0,0,5 * delegateWidth, 5 * delegateHeight); // just ensure all items fit
 +
 +    // these initial items should not trigger GridView.onAdd
 +    for (int i=0; i<initialItemCount; i++)
 +        model.addItem("dummy value", "dummy value");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("delegateWidth", delegateWidth);
 +    ctxt->setContextProperty("delegateHeight", delegateHeight);
 +    canvas->setSource(testFileUrl("attachedSignals.qml"));
 +
 +    QObject *object = canvas->rootObject();
 +    object->setProperty("width", canvas->width());
 +    object->setProperty("height", canvas->height());
 +    qApp->processEvents();
 +
 +    QList<QPair<QString, QString> > items;
 +    for (int i=0; i<itemsToAdd; i++)
 +        items << qMakePair(QString("value %1").arg(i), QString::number(i));
 +    model.addItems(items);
 +
 +    QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(canvas->rootObject())->count());
 +    qApp->processEvents();
 +
 +    QVariantList result = object->property("addedDelegates").toList();
 +    QTRY_COMPARE(result.count(), items.count());
 +    for (int i=0; i<items.count(); i++)
 +        QCOMPARE(result[i].toString(), items[i].first);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::onAdd_data()
 +{
 +    QTest::addColumn<int>("initialItemCount");
 +    QTest::addColumn<int>("itemsToAdd");
 +
 +    QTest::newRow("0, add 1") << 0 << 1;
 +    QTest::newRow("0, add 2") << 0 << 2;
 +    QTest::newRow("0, add 10") << 0 << 10;
 +
 +    QTest::newRow("1, add 1") << 1 << 1;
 +    QTest::newRow("1, add 2") << 1 << 2;
 +    QTest::newRow("1, add 10") << 1 << 10;
 +
 +    QTest::newRow("5, add 1") << 5 << 1;
 +    QTest::newRow("5, add 2") << 5 << 2;
 +    QTest::newRow("5, add 10") << 5 << 10;
 +}
 +
 +void tst_QQuickGridView::onRemove()
 +{
 +    QFETCH(int, initialItemCount);
 +    QFETCH(int, indexToRemove);
 +    QFETCH(int, removeCount);
 +
 +    const int delegateWidth = 50;
 +    const int delegateHeight = 100;
 +    QaimModel model;
 +    for (int i=0; i<initialItemCount; i++)
 +        model.addItem(QString("value %1").arg(i), "dummy value");
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("delegateWidth", delegateWidth);
 +    ctxt->setContextProperty("delegateHeight", delegateHeight);
 +    canvas->setSource(testFileUrl("attachedSignals.qml"));
 +    QObject *object = canvas->rootObject();
 +
 +    model.removeItems(indexToRemove, removeCount);
 +    QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(canvas->rootObject())->count());
 +    QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::onRemove_data()
 +{
 +    QTest::addColumn<int>("initialItemCount");
 +    QTest::addColumn<int>("indexToRemove");
 +    QTest::addColumn<int>("removeCount");
 +
 +    QTest::newRow("remove first") << 1 << 0 << 1;
 +    QTest::newRow("two items, remove first") << 2 << 0 << 1;
 +    QTest::newRow("two items, remove last") << 2 << 1 << 1;
 +    QTest::newRow("two items, remove all") << 2 << 0 << 2;
 +
 +    QTest::newRow("four items, remove first") << 4 << 0 << 1;
 +    QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
 +    QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
 +    QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
 +    QTest::newRow("four items, remove last") << 4 << 3 << 1;
 +    QTest::newRow("four items, remove all") << 4 << 0 << 4;
 +
 +    QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
 +    QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
 +    QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
 +}
 +
 +void tst_QQuickGridView::columnCount()
 +{
 +    QQuickView canvas;
 +    canvas.setSource(testFileUrl("gridview4.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +
 +    QQuickGridView *view = qobject_cast<QQuickGridView*>(canvas.rootObject());
 +
 +    QCOMPARE(view->cellWidth(), qreal(405)/qreal(9));
 +    QCOMPARE(view->cellHeight(), qreal(100));
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(view, "delegate");
 +    QCOMPARE(items.size(), 18);
 +    QCOMPARE(items.at(8)->y(), qreal(0));
 +    QCOMPARE(items.at(9)->y(), qreal(100));
 +}
 +
 +void tst_QQuickGridView::margins()
 +{
 +    {
 +        QQuickView *canvas = createView();
 +
 +        QaimModel model;
 +        for (int i = 0; i < 40; i++)
 +            model.addItem("Item" + QString::number(i), "");
 +
 +        QQmlContext *ctxt = canvas->rootContext();
 +        ctxt->setContextProperty("testModel", &model);
 +        ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +
 +        canvas->setSource(testFileUrl("margins.qml"));
 +        canvas->show();
 +        qApp->processEvents();
 +
 +        QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +        QTRY_VERIFY(gridview != 0);
 +        QQuickItem *contentItem = gridview->contentItem();
 +        QTRY_VERIFY(contentItem != 0);
 +        QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +        QCOMPARE(gridview->contentX(), -30.);
 +        QCOMPARE(gridview->xOrigin(), 0.);
 +
 +        // check end bound
 +        gridview->positionViewAtEnd();
 +        qreal pos = gridview->contentX();
 +        gridview->setContentX(pos + 80);
 +        gridview->returnToBounds();
 +        QTRY_COMPARE(gridview->contentX(), pos + 50);
 +
 +        // remove item before visible and check that left margin is maintained
 +        // and xOrigin is updated
 +        gridview->setContentX(200);
 +        model.removeItems(0, 4);
 +        QTest::qWait(100);
 +        gridview->setContentX(-50);
 +        gridview->returnToBounds();
 +        QCOMPARE(gridview->xOrigin(), 100.);
 +        QTRY_COMPARE(gridview->contentX(), 70.);
 +
 +        // reduce left margin
 +        gridview->setLeftMargin(20);
 +        QCOMPARE(gridview->xOrigin(), 100.);
 +        QTRY_COMPARE(gridview->contentX(), 80.);
 +
 +        // check end bound
 +        gridview->positionViewAtEnd();
 +        QCOMPARE(gridview->xOrigin(), 0.); // positionViewAtEnd() resets origin
 +        pos = gridview->contentX();
 +        gridview->setContentX(pos + 80);
 +        gridview->returnToBounds();
 +        QTRY_COMPARE(gridview->contentX(), pos + 50);
 +
 +        // reduce right margin
 +        pos = gridview->contentX();
 +        gridview->setRightMargin(40);
 +        QCOMPARE(gridview->xOrigin(), 0.);
 +        QTRY_COMPARE(gridview->contentX(), pos-10);
 +
 +        delete canvas;
 +    }
 +    {
 +        //RTL
 +        QQuickView *canvas = createView();
 +        canvas->show();
 +
 +        QaimModel model;
 +        for (int i = 0; i < 40; i++)
 +            model.addItem("Item" + QString::number(i), "");
 +
 +        QQmlContext *ctxt = canvas->rootContext();
 +        ctxt->setContextProperty("testModel", &model);
 +        ctxt->setContextProperty("testRightToLeft", QVariant(true));
 +
 +        canvas->setSource(testFileUrl("margins.qml"));
 +        qApp->processEvents();
 +
 +        QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +        QTRY_VERIFY(gridview != 0);
 +
 +        QQuickItem *contentItem = gridview->contentItem();
 +        QTRY_VERIFY(contentItem != 0);
 +
 +        QCOMPARE(gridview->contentX(), -240+30.);
 +        QCOMPARE(gridview->xOrigin(), 0.);
 +
 +        // check end bound
 +        gridview->positionViewAtEnd();
 +        qreal pos = gridview->contentX();
 +        gridview->setContentX(pos - 80);
 +        gridview->returnToBounds();
 +        QTRY_COMPARE(gridview->contentX(), pos - 50);
 +
 +        // remove item before visible and check that left margin is maintained
 +        // and xOrigin is updated
 +        gridview->setContentX(-400);
 +        model.removeItems(0, 4);
 +        QTest::qWait(100);
 +        gridview->setContentX(-240+50);
 +        gridview->returnToBounds();
 +        QCOMPARE(gridview->xOrigin(), -100.);
 +        QTRY_COMPARE(gridview->contentX(), -240-70.);
 +
 +        // reduce left margin (i.e. right side due to RTL)
 +        pos = gridview->contentX();
 +        gridview->setLeftMargin(20);
 +        QCOMPARE(gridview->xOrigin(), -100.);
 +        QTRY_COMPARE(gridview->contentX(), -240-80.);
 +
 +        // check end bound
 +        gridview->positionViewAtEnd();
 +        QCOMPARE(gridview->xOrigin(), 0.); // positionViewAtEnd() resets origin
 +        pos = gridview->contentX();
 +        gridview->setContentX(pos - 80);
 +        gridview->returnToBounds();
 +        QTRY_COMPARE(gridview->contentX(), pos - 50);
 +
 +        // reduce right margin (i.e. left side due to RTL)
 +        pos = gridview->contentX();
 +        gridview->setRightMargin(40);
 +        QCOMPARE(gridview->xOrigin(), 0.);
 +        QTRY_COMPARE(gridview->contentX(), pos+10);
 +
 +        delete canvas;
 +    }
 +}
 +
 +void tst_QQuickGridView::creationContext()
 +{
 +    QQuickView canvas;
 +    canvas.setGeometry(0,0,240,320);
 +    canvas.setSource(testFileUrl("creationContext.qml"));
 +    qApp->processEvents();
 +
 +    QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
 +    QVERIFY(rootItem);
 +    QVERIFY(rootItem->property("count").toInt() > 0);
 +
 +    QQuickItem *item;
 +    QVERIFY(item = rootItem->findChild<QQuickItem *>("listItem"));
 +    QCOMPARE(item->property("text").toString(), QString("Hello!"));
 +    QVERIFY(item = rootItem->findChild<QQuickItem *>("header"));
 +    QCOMPARE(item->property("text").toString(), QString("Hello!"));
 +    QVERIFY(item = rootItem->findChild<QQuickItem *>("footer"));
 +    QCOMPARE(item->property("text").toString(), QString("Hello!"));
 +}
 +
 +void tst_QQuickGridView::snapToRow_data()
 +{
 +    QTest::addColumn<QQuickGridView::Flow>("flow");
 +    QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
 +    QTest::addColumn<int>("highlightRangeMode");
 +    QTest::addColumn<QPoint>("flickStart");
 +    QTest::addColumn<QPoint>("flickEnd");
 +    QTest::addColumn<qreal>("snapAlignment");
 +    QTest::addColumn<qreal>("endExtent");
 +    QTest::addColumn<qreal>("startExtent");
 +
 +    QTest::newRow("vertical, left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
 +
 +    QTest::newRow("horizontal, left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
 +
 +    QTest::newRow("horizontal, right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 << -240.0;
 +
 +    QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
 +
 +    QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
 +
 +    QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 - 140.0 << -220.0;
 +}
 +
 +void tst_QQuickGridView::snapToRow()
 +{
 +    QFETCH(QQuickGridView::Flow, flow);
 +    QFETCH(Qt::LayoutDirection, layoutDirection);
 +    QFETCH(int, highlightRangeMode);
 +    QFETCH(QPoint, flickStart);
 +    QFETCH(QPoint, flickEnd);
 +    QFETCH(qreal, snapAlignment);
 +    QFETCH(qreal, endExtent);
 +    QFETCH(qreal, startExtent);
 +
 +    QQuickView *canvas = createView();
 +
 +    canvas->setSource(testFileUrl("snapToRow.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    gridview->setFlow(flow);
 +    gridview->setLayoutDirection(layoutDirection);
 +    gridview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    // confirm that a flick hits an item boundary
 +    flick(canvas, flickStart, flickEnd, 180);
 +    QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
 +    if (flow == QQuickGridView::LeftToRight)
 +        QCOMPARE(qreal(fmod(gridview->contentY(),80.0)), snapAlignment);
 +    else
 +        QCOMPARE(qreal(fmod(gridview->contentX(),80.0)), snapAlignment);
 +
 +    // flick to end
 +    do {
 +        flick(canvas, flickStart, flickEnd, 180);
 +        QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
 +    } while (flow == QQuickGridView::LeftToRight
 +           ? !gridview->isAtYEnd()
 +           : layoutDirection == Qt::LeftToRight ? !gridview->isAtXEnd() : !gridview->isAtXBeginning());
 +
 +    if (flow == QQuickGridView::LeftToRight)
 +        QCOMPARE(gridview->contentY(), endExtent);
 +    else
 +        QCOMPARE(gridview->contentX(), endExtent);
 +
 +    // flick to start
 +    do {
 +        flick(canvas, flickEnd, flickStart, 180);
 +        QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
 +    } while (flow == QQuickGridView::LeftToRight
 +           ? !gridview->isAtYBeginning()
 +           : layoutDirection == Qt::LeftToRight ? !gridview->isAtXBeginning() : !gridview->isAtXEnd());
 +
 +    if (flow == QQuickGridView::LeftToRight)
 +        QCOMPARE(gridview->contentY(), startExtent);
 +    else
 +        QCOMPARE(gridview->contentX(), startExtent);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::snapOneRow_data()
 +{
 +    QTest::addColumn<QQuickGridView::Flow>("flow");
 +    QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
 +    QTest::addColumn<int>("highlightRangeMode");
 +    QTest::addColumn<QPoint>("flickStart");
 +    QTest::addColumn<QPoint>("flickEnd");
 +    QTest::addColumn<qreal>("snapAlignment");
 +    QTest::addColumn<qreal>("endExtent");
 +    QTest::addColumn<qreal>("startExtent");
 +
 +    QTest::newRow("vertical, left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(20, 200) << QPoint(20, 20) << 100.0 << 360.0 << 0.0;
 +
 +    QTest::newRow("horizontal, left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(200, 20) << QPoint(20, 20) << 100.0 << 360.0 << 0.0;
 +
 +    QTest::newRow("horizontal, right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(20, 20) << QPoint(200, 20) << -340.0 << -360.0 - 240.0 << -240.0;
 +
 +    QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(20, 200) << QPoint(20, 20) << 100.0 << 460.0 << -20.0;
 +
 +    QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(200, 20) << QPoint(20, 20) << 100.0 << 460.0 << -20.0;
 +
 +    QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(20, 20) << QPoint(200, 20) << -340.0 << -360.0 - 240.0 - 100.0 << -220.0;
 +}
 +
 +void tst_QQuickGridView::snapOneRow()
 +{
 +    QFETCH(QQuickGridView::Flow, flow);
 +    QFETCH(Qt::LayoutDirection, layoutDirection);
 +    QFETCH(int, highlightRangeMode);
 +    QFETCH(QPoint, flickStart);
 +    QFETCH(QPoint, flickEnd);
 +    QFETCH(qreal, snapAlignment);
 +    QFETCH(qreal, endExtent);
 +    QFETCH(qreal, startExtent);
 +
 +    QQuickView *canvas = createView();
 +
 +    canvas->setSource(testFileUrl("snapOneRow.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +
 +    gridview->setFlow(flow);
 +    gridview->setLayoutDirection(layoutDirection);
 +    gridview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QSignalSpy currentIndexSpy(gridview, SIGNAL(currentIndexChanged()));
 +
 +    // confirm that a flick hits next row boundary
 +    flick(canvas, flickStart, flickEnd, 180);
 +    QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
 +    if (flow == QQuickGridView::LeftToRight)
 +        QCOMPARE(gridview->contentY(), snapAlignment);
 +    else
 +        QCOMPARE(gridview->contentX(), snapAlignment);
 +
 +    if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
 +        QCOMPARE(gridview->currentIndex(), 2);
 +        QCOMPARE(currentIndexSpy.count(), 1);
 +    }
 +
 +    // flick to end
 +    do {
 +        flick(canvas, flickStart, flickEnd, 180);
 +        QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
 +    } while (flow == QQuickGridView::LeftToRight
 +           ? !gridview->isAtYEnd()
 +           : layoutDirection == Qt::LeftToRight ? !gridview->isAtXEnd() : !gridview->isAtXBeginning());
 +
 +    if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
 +        QCOMPARE(gridview->currentIndex(), 8);
 +        QCOMPARE(currentIndexSpy.count(), 4);
 +    }
 +
 +    if (flow == QQuickGridView::LeftToRight)
 +        QCOMPARE(gridview->contentY(), endExtent);
 +    else
 +        QCOMPARE(gridview->contentX(), endExtent);
 +
 +    // flick to start
 +    do {
 +        flick(canvas, flickEnd, flickStart, 180);
 +        QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
 +    } while (flow == QQuickGridView::LeftToRight
 +           ? !gridview->isAtYBeginning()
 +           : layoutDirection == Qt::LeftToRight ? !gridview->isAtXBeginning() : !gridview->isAtXEnd());
 +
 +    if (flow == QQuickGridView::LeftToRight)
 +        QCOMPARE(gridview->contentY(), startExtent);
 +    else
 +        QCOMPARE(gridview->contentX(), startExtent);
 +
 +    if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
 +        QCOMPARE(gridview->currentIndex(), 0);
 +        QCOMPARE(currentIndexSpy.count(), 8);
 +    }
 +
 +    delete canvas;
 +}
 +
 +
 +void tst_QQuickGridView::unaligned()
 +{
 +    QQuickView *canvas = createView();
 +    canvas->show();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 10; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("unaligned.qml"));
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = qobject_cast<QQuickGridView*>(canvas->rootObject());
 +    QVERIFY(gridview != 0);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem != 0);
 +
 +    for (int i = 0; i < 10; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QVERIFY(item);
 +        QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
 +        QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
 +    }
 +
 +    // appending
 +    for (int i = 10; i < 18; ++i) {
 +        model.addItem("Item" + QString::number(i), "");
 +        QQuickItem *item = 0;
 +        QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
 +        QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
 +        QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
 +    }
 +
 +    // inserting
 +    for (int i = 0; i < 10; ++i) {
 +        model.insertItem(i, "Item" + QString::number(i), "");
 +        QQuickItem *item = 0;
 +        QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
 +        QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
 +        QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
 +    }
 +
 +    // removing
 +    model.removeItems(7, 10);
 +    QTRY_COMPARE(model.count(), gridview->count());
 +    for (int i = 0; i < 18; ++i) {
 +        QQuickItem *item = 0;
 +        QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
 +        QCOMPARE(item->x(), qreal(i%9)*gridview->cellWidth());
 +        QCOMPARE(item->y(), qreal(i/9)*gridview->cellHeight());
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::populateTransitions()
 +{
 +    QFETCH(bool, staticallyPopulate);
 +    QFETCH(bool, dynamicallyPopulate);
 +    QFETCH(bool, usePopulateTransition);
 +
 +    QPointF transitionFrom(-50, -50);
 +    QPointF transitionVia(100, 100);
 +    QaimModel model_transitionFrom;
 +    QaimModel model_transitionVia;
 +
 +    QaimModel model;
 +    if (staticallyPopulate) {
 +        for (int i = 0; i < 30; i++)
 +            model.addItem("item" + QString::number(i), "");
 +    }
 +
 +    QQuickView *canvas = createView();
 +    canvas->rootContext()->setContextProperty("testModel", &model);
 +    canvas->rootContext()->setContextProperty("usePopulateTransition", usePopulateTransition);
 +    canvas->rootContext()->setContextProperty("dynamicallyPopulate", dynamicallyPopulate);
 +    canvas->rootContext()->setContextProperty("transitionFrom", transitionFrom);
 +    canvas->rootContext()->setContextProperty("transitionVia", transitionVia);
 +    canvas->rootContext()->setContextProperty("model_transitionFrom", &model_transitionFrom);
 +    canvas->rootContext()->setContextProperty("model_transitionVia", &model_transitionVia);
 +    canvas->setSource(testFileUrl("populateTransitions.qml"));
 +    canvas->show();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QVERIFY(gridview);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem);
 +
 +    if (staticallyPopulate || dynamicallyPopulate) {
 +        // check the populate transition is run
 +        if (usePopulateTransition) {
 +            QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), 19);
 +        } else {
 +            QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +            QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), 0);
 +        }
 +        QTRY_COMPARE(gridview->property("countAddTransitions").toInt(), 0);
 +    } else {
 +        QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +    }
 +
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    if (usePopulateTransition)
 +        QCOMPARE(itemCount, gridview->property("countPopulateTransitions").toInt());
 +    for (int i=0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), (i%3)*80.0);
 +        QCOMPARE(item->y(), (i/3)*60.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    // add an item and check this is done with add transition, not populate
 +    model.insertItem(0, "another item", "");
 +    QTRY_COMPARE(gridview->property("countAddTransitions").toInt(), 1);
 +    QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(),
 +                 (usePopulateTransition && (staticallyPopulate || dynamicallyPopulate)) ? 19 : 0);
 +
 +    // clear the model
 +    canvas->rootContext()->setContextProperty("testModel", QVariant());
 +    QTRY_COMPARE(gridview->count(), 0);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper").count(), 0);
 +    gridview->setProperty("countPopulateTransitions", 0);
 +    gridview->setProperty("countAddTransitions", 0);
 +
 +    // set to a valid model and check populate transition is run a second time
 +    model.clear();
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("item" + QString::number(i), "");
 +    canvas->rootContext()->setContextProperty("testModel", &model);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), usePopulateTransition ? 19 : 0);
 +    QTRY_COMPARE(gridview->property("countAddTransitions").toInt(), 0);
 +
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    if (usePopulateTransition)
 +        QCOMPARE(itemCount, gridview->property("countPopulateTransitions").toInt());
 +    for (int i=0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), (i%3)*80.0);
 +        QCOMPARE(item->y(), (i/3)*60.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    // reset model and check populate transition is run again
 +    gridview->setProperty("countPopulateTransitions", 0);
 +    gridview->setProperty("countAddTransitions", 0);
 +    model.reset();
 +    QTRY_COMPARE(gridview->property("countPopulateTransitions").toInt(), usePopulateTransition ? 19 : 0);
 +    QTRY_COMPARE(gridview->property("countAddTransitions").toInt(), 0);
 +
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    if (usePopulateTransition)
 +        QCOMPARE(itemCount, gridview->property("countPopulateTransitions").toInt());
 +    for (int i=0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), (i%3)*80.0);
 +        QCOMPARE(item->y(), (i/3)*60.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::populateTransitions_data()
 +{
 +    QTest::addColumn<bool>("staticallyPopulate");
 +    QTest::addColumn<bool>("dynamicallyPopulate");
 +    QTest::addColumn<bool>("usePopulateTransition");
 +
 +    QTest::newRow("static") << true << false << true;
 +    QTest::newRow("static, no populate") << true << false << false;
 +
 +    QTest::newRow("dynamic") << false << true << true;
 +    QTest::newRow("dynamic, no populate") << false << true << false;
 +
 +    QTest::newRow("empty to start with") << false << false << true;
 +    QTest::newRow("empty to start with, no populate") << false << false << false;
 +}
 +
 +void tst_QQuickGridView::addTransitions()
 +{
 +    QFETCH(int, initialItemCount);
 +    QFETCH(bool, shouldAnimateTargets);
 +    QFETCH(qreal, contentY);
 +    QFETCH(int, insertionIndex);
 +    QFETCH(int, insertionCount);
 +    QFETCH(ListRange, expectedDisplacedIndexes);
 +
 +    // added items should start here
 +    QPointF targetItems_transitionFrom(-50, -50);
 +
 +    // displaced items should pass through this point
 +    QPointF displacedItems_transitionVia(100, 100);
 +
 +    QaimModel model;
 +    for (int i = 0; i < initialItemCount; i++)
 +        model.addItem("Original item" + QString::number(i), "");
 +    QaimModel model_targetItems_transitionFrom;
 +    QaimModel model_displacedItems_transitionVia;
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
 +    ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
 +    ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
 +    ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
 +    canvas->setSource(testFileUrl("addTransitions.qml"));
 +    canvas->show();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    if (contentY != 0) {
 +        gridview->setContentY(contentY);
 +        QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +    }
 +
 +    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
 +
 +    // only target items that will become visible should be animated
 +    QList<QPair<QString, QString> > newData;
 +    QList<QPair<QString, QString> > expectedTargetData;
 +    QList<int> targetIndexes;
 +    if (shouldAnimateTargets) {
 +        for (int i=insertionIndex; i<insertionIndex+insertionCount; i++) {
 +            newData << qMakePair(QString("New item %1").arg(i), QString(""));
 +
 +            // last visible item is the first item of the row beneath the view
 +            if (i >= (contentY / 60)*3 && i < qCeil((contentY + gridview->height()) / 60.0)*3) {
 +                expectedTargetData << newData.last();
 +                targetIndexes << i;
 +            }
 +        }
 +        QVERIFY(expectedTargetData.count() > 0);
 +    }
 +
 +    // start animation
 +    if (!newData.isEmpty()) {
 +        model.insertItems(insertionIndex, newData);
 +        QTRY_COMPARE(model.count(), gridview->count());
 +    }
 +
 +    QList<QQuickItem *> targetItems = findItems<QQuickItem>(contentItem, "wrapper", targetIndexes);
 +
 +    if (shouldAnimateTargets) {
 +        QTRY_COMPARE(gridview->property("targetTransitionsDone").toInt(), expectedTargetData.count());
 +        QTRY_COMPARE(gridview->property("displaceTransitionsDone").toInt(),
 +                     expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0);
 +
 +        // check the target and displaced items were animated
 +        model_targetItems_transitionFrom.matchAgainst(expectedTargetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos");
 +        model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim");
 +
 +        // check attached properties
 +        matchItemsAndIndexes(gridview->property("targetTrans_items").toMap(), model, targetIndexes);
 +        matchIndexLists(gridview->property("targetTrans_targetIndexes").toList(), targetIndexes);
 +        matchItemLists(gridview->property("targetTrans_targetItems").toList(), targetItems);
 +        if (expectedDisplacedIndexes.isValid()) {
 +            // adjust expectedDisplacedIndexes to their final values after the move
 +            QList<int> displacedIndexes = adjustIndexesForAddDisplaced(expectedDisplacedIndexes.indexes, insertionIndex, insertionCount);
 +            matchItemsAndIndexes(gridview->property("displacedTrans_items").toMap(), model, displacedIndexes);
 +            matchIndexLists(gridview->property("displacedTrans_targetIndexes").toList(), targetIndexes);
 +            matchItemLists(gridview->property("displacedTrans_targetItems").toList(), targetItems);
 +        }
 +    } else {
 +        QTRY_COMPARE(model_targetItems_transitionFrom.count(), 0);
 +        QTRY_COMPARE(model_displacedItems_transitionVia.count(), 0);
 +    }
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    int firstVisibleIndex = -1;
 +    for (int i=0; i<items.count(); i++) {
 +        if (items[i]->y() >= contentY) {
 +            QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +            firstVisibleIndex = e.evaluate().toInt();
 +            break;
 +        }
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // verify all items moved to the correct final positions
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), (i%3)*80.0);
 +        QCOMPARE(item->y(), (i/3)*60.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QCOMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::addTransitions_data()
 +{
 +    QTest::addColumn<int>("initialItemCount");
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<bool>("shouldAnimateTargets");
 +    QTest::addColumn<int>("insertionIndex");
 +    QTest::addColumn<int>("insertionCount");
 +    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
 +
 +    // if inserting a full row before visible index, items don't appear or animate in, even if there are > 1 new items
 +    QTest::newRow("insert 1, just before start")
 +            << 30 << 20.0 << false
 +            << 0 << 1 << ListRange();
 +    QTest::newRow("insert 1, way before start")
 +            << 30 << 20.0 << false
 +            << 0 << 1 << ListRange();
 +    QTest::newRow("insert multiple, just before start")
 +            << 30 << 100.0 << false
 +            << 0 << 3 << ListRange();
 +    QTest::newRow("insert multiple (< 1 row), just before start")
 +            << 30 << 100.0 << false
 +            << 0 << 2 << ListRange();
 +    QTest::newRow("insert multiple, way before start")
 +            << 30 << 100.0 << false
 +            << 0 << 3 << ListRange();
 +
 +    QTest::newRow("insert 1 at start")
 +            << 30 << 0.0 << true
 +            << 0 << 1 << ListRange(0, 17);
 +    QTest::newRow("insert multiple at start")
 +            << 30 << 0.0 << true
 +            << 0 << 3 << ListRange(0, 17);
 +    QTest::newRow("insert multiple (> 1 row) at start")
 +            << 30 << 0.0 << true
 +            << 0 << 5 << ListRange(0, 17);
 +    QTest::newRow("insert 1 at start, content y not 0")
 +            << 30 << 60.0 << true  // first visible is index 3
 +            << 3 << 1 << ListRange(0 + 3, 17 + 3);
 +    QTest::newRow("insert multiple at start, content y not 0")
 +            << 30 << 60.0 << true    // first visible is index 3
 +            << 3 << 3 << ListRange(0 + 3, 17 + 3);
 +    QTest::newRow("insert multiple (> 1 row) at start, content y not 0")
 +            << 30 << 60.0 << true    // first visible is index 3
 +            << 3 << 5 << ListRange(0 + 3, 17 + 3);
 +
 +    QTest::newRow("insert 1 at start, to empty grid")
 +            << 0 << 0.0 << true
 +            << 0 << 1 << ListRange();
 +    QTest::newRow("insert multiple at start, to empty grid")
 +            << 0 << 0.0 << true
 +            << 0 << 3 << ListRange();
 +
 +    QTest::newRow("insert 1 at middle")
 +            << 30 << 0.0 << true
 +            << 7 << 1 << ListRange(7, 17);
 +    QTest::newRow("insert multiple at middle")
 +            << 30 << 0.0 << true
 +            << 7 << 3 << ListRange(7, 17);
 +    QTest::newRow("insert multiple (> 1 row) at middle")
 +            << 30 << 0.0 << true
 +            << 7 << 5 << ListRange(7, 17);
 +
 +    QTest::newRow("insert 1 at bottom")
 +            << 30 << 0.0 << true
 +            << 17 << 1 << ListRange(17, 17);
 +    QTest::newRow("insert multiple at bottom")
 +            << 30 << 0.0 << true
 +            << 17 << 3 << ListRange(17, 17);
 +    QTest::newRow("insert 1 at bottom, content y not 0")
 +            << 30 << 20.0 * 3 << true
 +            << 17 + 3 << 1 << ListRange(17 + 3, 17 + 3);
 +    QTest::newRow("insert multiple at bottom, content y not 0")
 +            << 30 << 20.0 * 3 << true
 +            << 17 + 3 << 3 << ListRange(17 + 3, 17 + 3);
 +
 +
 +    // items added after the last visible will not be animated in, since they
 +    // do not appear in the final view
 +    QTest::newRow("insert 1 after end")
 +            << 30 << 0.0 << false
 +            << 18 << 1 << ListRange();
 +    QTest::newRow("insert multiple after end")
 +            << 30 << 0.0 << false
 +            << 18 << 3 << ListRange();
 +}
 +
 +void tst_QQuickGridView::moveTransitions()
 +{
 +    QFETCH(int, initialItemCount);
 +    QFETCH(qreal, contentY);
 +    QFETCH(qreal, itemsOffsetAfterMove);
 +    QFETCH(int, moveFrom);
 +    QFETCH(int, moveTo);
 +    QFETCH(int, moveCount);
 +    QFETCH(ListRange, expectedDisplacedIndexes);
 +
 +    // target and displaced items should pass through these points
 +    QPointF targetItems_transitionVia(-50, 50);
 +    QPointF displacedItems_transitionVia(100, 100);
 +
 +    QaimModel model;
 +    for (int i = 0; i < initialItemCount; i++)
 +        model.addItem("Original item" + QString::number(i), "");
 +    QaimModel model_targetItems_transitionVia;
 +    QaimModel model_displacedItems_transitionVia;
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("model_targetItems_transitionVia", &model_targetItems_transitionVia);
 +    ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
 +    ctxt->setContextProperty("targetItems_transitionVia", targetItems_transitionVia);
 +    ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
 +    canvas->setSource(testFileUrl("moveTransitions.qml"));
 +    canvas->show();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QQuickText *name;
 +
 +    if (contentY != 0) {
 +        gridview->setContentY(contentY);
 +        QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +    }
 +
 +    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
 +
 +    // Items moving to *or* from visible positions should be animated.
 +    // Otherwise, they should not be animated.
 +    QList<QPair<QString, QString> > expectedTargetData;
 +    QList<int> targetIndexes;
 +    for (int i=moveFrom; i<moveFrom+moveCount; i++) {
 +        int toIndex = moveTo + (i - moveFrom);
 +        int firstVisibleIndex = (contentY / 60) * 3;
 +        int lastVisibleIndex = (qCeil((contentY + gridview->height()) / 60.0)*3) - 1;
 +        if ((i >= firstVisibleIndex && i <= lastVisibleIndex)
 +                || (toIndex >= firstVisibleIndex && toIndex <= lastVisibleIndex)) {
 +            expectedTargetData << qMakePair(model.name(i), model.number(i));
 +            targetIndexes << i;
 +        }
 +    }
 +    // ViewTransition.index provides the indices that items are moving to, not from
 +    targetIndexes = adjustIndexesForMove(targetIndexes, moveFrom, moveTo, moveCount);
 +
 +    // start animation
 +    model.moveItems(moveFrom, moveTo, moveCount);
 +
 +    QTRY_COMPARE(gridview->property("targetTransitionsDone").toInt(), expectedTargetData.count());
 +    QTRY_COMPARE(gridview->property("displaceTransitionsDone").toInt(),
 +                 expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0);
 +
 +    QList<QQuickItem *> targetItems = findItems<QQuickItem>(contentItem, "wrapper", targetIndexes);
 +
 +    // check the target and displaced items were animated
 +    model_targetItems_transitionVia.matchAgainst(expectedTargetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos");
 +    model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim");
 +
 +    // check attached properties
 +    matchItemsAndIndexes(gridview->property("targetTrans_items").toMap(), model, targetIndexes);
 +    matchIndexLists(gridview->property("targetTrans_targetIndexes").toList(), targetIndexes);
 +    matchItemLists(gridview->property("targetTrans_targetItems").toList(), targetItems);
 +    if (expectedDisplacedIndexes.isValid()) {
 +        // adjust expectedDisplacedIndexes to their final values after the move
 +        QList<int> displacedIndexes = adjustIndexesForMove(expectedDisplacedIndexes.indexes, moveFrom, moveTo, moveCount);
 +        matchItemsAndIndexes(gridview->property("displacedTrans_items").toMap(), model, displacedIndexes);
 +        matchIndexLists(gridview->property("displacedTrans_targetIndexes").toList(), targetIndexes);
 +        matchItemLists(gridview->property("displacedTrans_targetItems").toList(), targetItems);
 +    }
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    int firstVisibleIndex = -1;
 +    for (int i=0; i<items.count(); i++) {
 +        if (items[i]->y() >= contentY) {
 +            QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +            firstVisibleIndex = e.evaluate().toInt();
 +            break;
 +        }
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // verify all items moved to the correct final positions
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), (i%3)*80.0);
 +        QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::moveTransitions_data()
 +{
 +    QTest::addColumn<int>("initialItemCount");
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<qreal>("itemsOffsetAfterMove");
 +    QTest::addColumn<int>("moveFrom");
 +    QTest::addColumn<int>("moveTo");
 +    QTest::addColumn<int>("moveCount");
 +    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
 +
 +    QTest::newRow("move from above view, outside visible items, move 1") << 30 << 120.0 << 0.0
 +            << 1 << 10 << 1 << ListRange(6, 10);
 +    QTest::newRow("move from above view, outside visible items, move 1 (first item)") << 30 << 120.0 << 0.0
 +            << 0 << 10 << 1 << ListRange(6, 10);
 +    QTest::newRow("move from above view, outside visible items, move multiple") << 30 << 120.0 << 60.0
 +            << 1 << 10 << 3 << ListRange(13, 23);
 +    QTest::newRow("move from above view, mix of visible/non-visible") << 30 << 120.0 << 60.0
 +            << 1 << 10 << 6 << (ListRange(7, 15) + ListRange(16, 23));
 +    QTest::newRow("move from above view, mix of visible/non-visible (move first)") << 30 << 120.0 << 120.0
 +            << 0 << 10 << 6 << ListRange(16, 23);
 +
 +    QTest::newRow("move within view, move 1 down") << 30 << 0.0 << 0.0
 +            << 1 << 10 << 1 << ListRange(2, 10);
 +    QTest::newRow("move within view, move 1 down, move first item") << 30 << 0.0 << 0.0
 +            << 0 << 10 << 1 << ListRange(1, 10);
 +    QTest::newRow("move within view, move 1 down, move first item, contentY not 0") << 30 << 120.0 << 0.0
 +            << 0+6 << 10+6 << 1 << ListRange(1+6, 10+6);
 +    QTest::newRow("move within view, move 1 down, to last item") << 30 << 0.0 << 0.0
 +            << 10 << 17 << 1 << ListRange(11, 17);
 +    QTest::newRow("move within view, move first->last") << 30 << 0.0 << 0.0
 +            << 0 << 17 << 1 << ListRange(1, 17);
 +
 +    QTest::newRow("move within view, move multiple down") << 30 << 0.0 << 0.0
 +            << 1 << 10 << 3 << ListRange(4, 12);
 +    QTest::newRow("move within view, move multiple down, move first item") << 30 << 0.0 << 0.0
 +            << 0 << 10 << 3 << ListRange(3, 12);
 +    QTest::newRow("move within view, move multiple down, move first item, contentY not 0") << 30 << 60.0 << 0.0
 +            << 0+3 << 10+3 << 3 << ListRange(3+3, 12+3);
 +    QTest::newRow("move within view, move multiple down, displace last item") << 30 << 0.0 << 0.0
 +            << 5 << 15 << 3 << ListRange(8, 17);
 +    QTest::newRow("move within view, move multiple down, move first->last") << 30 << 0.0 << 0.0
 +            << 0 << 15 << 3 << ListRange(3, 17);
 +
 +    QTest::newRow("move within view, move 1 up") << 30 << 0.0 << 0.0
 +            << 10 << 1 << 1 << ListRange(1, 9);
 +    QTest::newRow("move within view, move 1 up, move to first index") << 30 << 0.0 << 0.0
 +            << 10 << 0 << 1 << ListRange(0, 9);
 +    QTest::newRow("move within view, move 1 up, move to first index, contentY not 0") << 30 << 120.0 << 0.0
 +            << 10+6 << 0+6 << 1 << ListRange(0+6, 9+6);
 +    QTest::newRow("move within view, move 1 up, move to first index, contentY not on item border") << 30 << 80.0 << 0.0
 +            << 10+3 << 0+3 << 1 << ListRange(0+3, 9+3);
 +    QTest::newRow("move within view, move 1 up, move last item") << 30 << 0.0 << 0.0
 +            << 17 << 10 << 1 << ListRange(10, 16);
 +    QTest::newRow("move within view, move 1 up, move last->first") << 30 << 0.0 << 0.0
 +            << 17 << 0 << 1 << ListRange(0, 16);
 +
 +    QTest::newRow("move within view, move multiple up") << 30 << 0.0 << 0.0
 +            << 10 << 1 << 3 << ListRange(1, 9);
 +    QTest::newRow("move within view, move multiple (> 1 row) up") << 30 << 0.0 << 0.0
 +            << 10 << 1 << 5 << ListRange(1, 9);
 +    QTest::newRow("move within view, move multiple up, move to first index") << 30 << 0.0 << 0.0
 +            << 10 << 0 << 3 << ListRange(0, 9);
 +    QTest::newRow("move within view, move multiple up, move to first index, contentY not 0") << 30 << 60.0 << 0.0
 +            << 10+3 << 0+3 << 3 << ListRange(0+3, 9+3);
 +    QTest::newRow("move within view, move multiple up (> 1 row), move to first index, contentY not on border") << 30 << 80.0 << 0.0
 +            << 10+3 << 0+3 << 5 << ListRange(0+3, 9+3);
 +    QTest::newRow("move within view, move multiple up, move last item") << 30 << 0.0 << 0.0
 +            << 15 << 5 << 3 << ListRange(5, 14);
 +    QTest::newRow("move within view, move multiple up, move last->first") << 30 << 0.0 << 0.0
 +            << 15 << 0 << 3 << ListRange(0, 14);
 +
 +    QTest::newRow("move from below view, move 1 up") << 30 << 0.0 << 0.0
 +            << 20 << 5 << 1 << ListRange(5, 17);
 +    QTest::newRow("move from below view, move 1 up, move to top") << 30 << 0.0 << 0.0
 +            << 20 << 0 << 1 << ListRange(0, 17);
 +    QTest::newRow("move from below view, move 1 up, move to top, contentY not 0") << 30 << 60.0 << 0.0
 +            << 25 << 3 << 1 << ListRange(0+3, 17+3);
 +    QTest::newRow("move from below view, move multiple (> 1 row) up") << 30 << 0.0 << 0.0
 +            << 20 << 5 << 5 << ListRange(5, 17);
 +    QTest::newRow("move from below view, move multiple up, move to top") << 30 << 0.0 << 0.0
 +            << 20 << 0 << 3 << ListRange(0, 17);
 +    QTest::newRow("move from below view, move multiple up, move to top, contentY not 0") << 30 << 60.0 << 0.0
 +            << 25 << 3 << 3 << ListRange(0+3, 17+3);
 +
 +    QTest::newRow("move from below view, move 1 up, move to bottom") << 30 << 0.0 << 0.0
 +            << 20 << 17 << 1 << ListRange(17, 17);
 +    QTest::newRow("move from below view, move 1 up, move to bottom, contentY not 0") << 30 << 60.0 << 0.0
 +            << 25 << 17+3 << 1 << ListRange(17+3, 17+3);
 +    QTest::newRow("move from below view, move multiple up, move to to bottom") << 30 << 0.0 << 0.0
 +            << 20 << 17 << 3 << ListRange(17, 17);
 +    QTest::newRow("move from below view, move multiple up, move to bottom, contentY not 0") << 30 << 60.0 << 0.0
 +            << 25 << 17+3 << 3 << ListRange(17+3, 17+3);
 +}
 +
 +void tst_QQuickGridView::removeTransitions()
 +{
 +    QFETCH(int, initialItemCount);
 +    QFETCH(bool, shouldAnimateTargets);
 +    QFETCH(qreal, contentY);
 +    QFETCH(int, removalIndex);
 +    QFETCH(int, removalCount);
 +    QFETCH(ListRange, expectedDisplacedIndexes);
 +
 +    // added items should end here
 +    QPointF targetItems_transitionTo(-50, -50);
 +
 +    // displaced items should pass through this points
 +    QPointF displacedItems_transitionVia(100, 100);
 +
 +    QaimModel model;
 +    for (int i = 0; i < initialItemCount; i++)
 +        model.addItem("Original item" + QString::number(i), "");
 +    QaimModel model_targetItems_transitionTo;
 +    QaimModel model_displacedItems_transitionVia;
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("model_targetItems_transitionTo", &model_targetItems_transitionTo);
 +    ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
 +    ctxt->setContextProperty("targetItems_transitionTo", targetItems_transitionTo);
 +    ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
 +    canvas->setSource(testFileUrl("removeTransitions.qml"));
 +    canvas->show();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
 +    if (contentY != 0) {
 +        gridview->setContentY(contentY);
 +        QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +    }
 +
 +    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
 +
 +    // only target items that are visible should be animated
 +    QList<QPair<QString, QString> > expectedTargetData;
 +    QList<int> targetIndexes;
 +    if (shouldAnimateTargets) {
 +        for (int i=removalIndex; i<removalIndex+removalCount; i++) {
 +            int firstVisibleIndex = (contentY / 60.0)*3;
 +            int lastVisibleIndex = (qCeil((contentY + gridview->height()) / 60.0)*3) - 1;
 +            if (i >= firstVisibleIndex && i <= lastVisibleIndex) {
 +                expectedTargetData << qMakePair(model.name(i), model.number(i));
 +                targetIndexes << i;
 +            }
 +        }
 +        QVERIFY(expectedTargetData.count() > 0);
 +    }
 +
 +    // calculate targetItems and expectedTargets before model changes
 +    QList<QQuickItem *> targetItems = findItems<QQuickItem>(contentItem, "wrapper", targetIndexes);
 +    QVariantMap expectedTargets;
 +    for (int i=0; i<targetIndexes.count(); i++)
 +        expectedTargets[model.name(targetIndexes[i])] = targetIndexes[i];
 +
 +    // start animation
 +    model.removeItems(removalIndex, removalCount);
 +    QTRY_COMPARE(model.count(), gridview->count());
 +
 +    if (shouldAnimateTargets || expectedDisplacedIndexes.isValid()) {
 +        QTRY_COMPARE(gridview->property("targetTransitionsDone").toInt(), expectedTargetData.count());
 +        QTRY_COMPARE(gridview->property("displaceTransitionsDone").toInt(),
 +                     expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0);
 +
 +        // check the target and displaced items were animated
 +        model_targetItems_transitionTo.matchAgainst(expectedTargetData, "wasn't animated to target 'to' pos", "shouldn't have been animated to target 'to' pos");
 +        model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim");
 +
 +        // check attached properties
 +        QCOMPARE(gridview->property("targetTrans_items").toMap(), expectedTargets);
 +        matchIndexLists(gridview->property("targetTrans_targetIndexes").toList(), targetIndexes);
 +        matchItemLists(gridview->property("targetTrans_targetItems").toList(), targetItems);
 +        if (expectedDisplacedIndexes.isValid()) {
 +            // adjust expectedDisplacedIndexes to their final values after the move
 +            QList<int> displacedIndexes = adjustIndexesForRemoveDisplaced(expectedDisplacedIndexes.indexes, removalIndex, removalCount);
 +            matchItemsAndIndexes(gridview->property("displacedTrans_items").toMap(), model, displacedIndexes);
 +            matchIndexLists(gridview->property("displacedTrans_targetIndexes").toList(), targetIndexes);
 +            matchItemLists(gridview->property("displacedTrans_targetItems").toList(), targetItems);
 +        }
 +    } else {
 +        QTRY_COMPARE(model_targetItems_transitionTo.count(), 0);
 +        QTRY_COMPARE(model_displacedItems_transitionVia.count(), 0);
 +    }
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    int itemCount = items.count();
 +    int firstVisibleIndex = -1;
 +    for (int i=0; i<items.count(); i++) {
 +        QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +        int index = e.evaluate().toInt();
 +        if (firstVisibleIndex < 0 && items[i]->y() >= contentY)
 +            firstVisibleIndex = index;
 +        else if (index < 0)
 +            itemCount--;    // exclude deleted items
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // verify all items moved to the correct final positions
 +    for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), (i%3)*80.0);
 +        QCOMPARE(item->y(), contentY + ((i-firstVisibleIndex)/3) * 60.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::removeTransitions_data()
 +{
 +    QTest::addColumn<int>("initialItemCount");
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<bool>("shouldAnimateTargets");
 +    QTest::addColumn<int>("removalIndex");
 +    QTest::addColumn<int>("removalCount");
 +    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
 +
 +    // All items that are visible following the remove operation should be animated.
 +    // Remove targets that are outside of the view should not be animated.
 +
 +    // For a GridView, removing any number of items other than a full row before the start
 +    // should displace all items in the view
 +    QTest::newRow("remove 1 before start")
 +            << 30 << 120.0 << false
 +            << 2 << 1 << ListRange(6, 24);    // 6-24 are displaced
 +    QTest::newRow("remove 1 row, before start")
 +            << 30 << 120.0 << false
 +            << 3 << 3 << ListRange();
 +    QTest::newRow("remove between 1-2 rows, before start")
 +            << 30 << 120.0 << false
 +            << 0 << 5 << ListRange(6, 25);
 +    QTest::newRow("remove 2 rows, before start")
 +            << 30 << 120.0 << false
 +            << 0 << 6 << ListRange();
 +    QTest::newRow("remove mix of before and after start")
 +            << 30 << 60.0 << true
 +            << 2 << 3 << ListRange(5, 23);  // 5-23 are displaced into view
 +
 +
 +    QTest::newRow("remove 1 from start")
 +            << 30 << 0.0 << true
 +            << 0 << 1 << ListRange(1, 18);  // 1-18 are displaced into view
 +    QTest::newRow("remove multiple from start")
 +            << 30 << 0.0 << true
 +            << 0 << 3 << ListRange(3, 20);  // 3-18 are displaced into view
 +    QTest::newRow("remove 1 from start, content y not 0")
 +            << 30 << 60.0 << true
 +            << 3 << 1 << ListRange(1 + 3, 18 + 3);
 +    QTest::newRow("remove multiple from start, content y not 0")
 +            << 30 << 60.0 << true
 +            << 3 << 3 << ListRange(3 + 3, 20 + 3);
 +
 +
 +    QTest::newRow("remove 1 from middle")
 +            << 30 << 0.0 << true
 +            << 5 << 1 << ListRange(6, 18);
 +    QTest::newRow("remove multiple from middle")
 +            << 30 << 0.0 << true
 +            << 5 << 3 << ListRange(8, 20);
 +
 +
 +    QTest::newRow("remove 1 from bottom")
 +            << 30 << 0.0 << true
 +            << 17 << 1 << ListRange(18, 18);
 +    QTest::newRow("remove multiple (1 row) from bottom")
 +            << 30 << 0.0 << true
 +            << 15 << 3 << ListRange(18, 20);
 +    QTest::newRow("remove multiple (> 1 row) from bottom")
 +            << 30 << 0.0 << true
 +            << 15 << 5 << ListRange(20, 22);
 +    QTest::newRow("remove 1 from bottom, content y not 0")
 +            << 30 << 60.0 << true
 +            << 17 + 3 << 1 << ListRange(18 + 3, 18 + 3);
 +    QTest::newRow("remove multiple (1 row) from bottom, content y not 0")
 +            << 30 << 60.0 << true
 +            << 15 + 3 << 3 << ListRange(18 + 3, 20 + 3);
 +
 +
 +    QTest::newRow("remove 1 after end")
 +            << 30 << 0.0 << false
 +            << 18 << 1 << ListRange();
 +    QTest::newRow("remove multiple after end")
 +            << 30 << 0.0 << false
 +            << 18 << 3 << ListRange();
 +}
 +
++void tst_QQuickGridView::displacedTransitions()
++{
++    QFETCH(bool, useDisplaced);
++    QFETCH(bool, displacedEnabled);
++    QFETCH(bool, useAddDisplaced);
++    QFETCH(bool, addDisplacedEnabled);
++    QFETCH(bool, useMoveDisplaced);
++    QFETCH(bool, moveDisplacedEnabled);
++    QFETCH(bool, useRemoveDisplaced);
++    QFETCH(bool, removeDisplacedEnabled);
++    QFETCH(ListChange, change);
++    QFETCH(ListRange, expectedDisplacedIndexes);
++
++    QaimModel model;
++    for (int i = 0; i < 30; i++)
++        model.addItem("Original item" + QString::number(i), "");
++    QaimModel model_displaced_transitionVia;
++    QaimModel model_addDisplaced_transitionVia;
++    QaimModel model_moveDisplaced_transitionVia;
++    QaimModel model_removeDisplaced_transitionVia;
++
++    QPointF displaced_transitionVia(-50, -100);
++    QPointF addDisplaced_transitionVia(-150, 100);
++    QPointF moveDisplaced_transitionVia(50, -100);
++    QPointF removeDisplaced_transitionVia(150, 100);
++
++    QQuickView *canvas = createView();
++    QQmlContext *ctxt = canvas->rootContext();
++    ctxt->setContextProperty("testModel", &model);
++    ctxt->setContextProperty("model_displaced_transitionVia", &model_displaced_transitionVia);
++    ctxt->setContextProperty("model_addDisplaced_transitionVia", &model_addDisplaced_transitionVia);
++    ctxt->setContextProperty("model_moveDisplaced_transitionVia", &model_moveDisplaced_transitionVia);
++    ctxt->setContextProperty("model_removeDisplaced_transitionVia", &model_removeDisplaced_transitionVia);
++    ctxt->setContextProperty("displaced_transitionVia", displaced_transitionVia);
++    ctxt->setContextProperty("addDisplaced_transitionVia", addDisplaced_transitionVia);
++    ctxt->setContextProperty("moveDisplaced_transitionVia", moveDisplaced_transitionVia);
++    ctxt->setContextProperty("removeDisplaced_transitionVia", removeDisplaced_transitionVia);
++    ctxt->setContextProperty("useDisplaced", useDisplaced);
++    ctxt->setContextProperty("displacedEnabled", displacedEnabled);
++    ctxt->setContextProperty("useAddDisplaced", useAddDisplaced);
++    ctxt->setContextProperty("addDisplacedEnabled", addDisplacedEnabled);
++    ctxt->setContextProperty("useMoveDisplaced", useMoveDisplaced);
++    ctxt->setContextProperty("moveDisplacedEnabled", moveDisplacedEnabled);
++    ctxt->setContextProperty("useRemoveDisplaced", useRemoveDisplaced);
++    ctxt->setContextProperty("removeDisplacedEnabled", removeDisplacedEnabled);
++    canvas->setSource(testFileUrl("displacedTransitions.qml"));
++    canvas->show();
++    qApp->processEvents();
++
++    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
++    QTRY_VERIFY(gridview != 0);
++    QQuickItem *contentItem = gridview->contentItem();
++    QVERIFY(contentItem != 0);
++    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
++
++    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
++    gridview->setProperty("displaceTransitionsDone", false);
++
++    switch (change.type) {
++        case ListChange::Inserted:
++        {
++            QList<QPair<QString, QString> > targetItemData;
++            for (int i=change.index; i<change.index + change.count; ++i)
++                targetItemData << qMakePair(QString("new item %1").arg(i), QString::number(i));
++            model.insertItems(change.index, targetItemData);
++            QTRY_COMPARE(model.count(), gridview->count());
++            break;
++        }
++        case ListChange::Removed:
++            model.removeItems(change.index, change.count);
++            QTRY_COMPARE(model.count(), gridview->count());
++            break;
++        case ListChange::Moved:
++            model.moveItems(change.index, change.to, change.count);
++            QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
++            break;
++        case ListChange::SetCurrent:
++        case ListChange::SetContentY:
++            break;
++    }
++    if ((useDisplaced && displacedEnabled)
++            || (useAddDisplaced && addDisplacedEnabled)
++            || (useMoveDisplaced && moveDisplacedEnabled)
++            || (useRemoveDisplaced && removeDisplacedEnabled)) {
++        QTRY_VERIFY(gridview->property("displaceTransitionsDone").toBool());
++    }
++
++    if (change.type == ListChange::Inserted && useAddDisplaced && addDisplacedEnabled)
++        model_addDisplaced_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with add displaced", "shouldn't have been animated with add displaced");
++    else
++        QCOMPARE(model_addDisplaced_transitionVia.count(), 0);
++    if (change.type == ListChange::Moved && useMoveDisplaced && moveDisplacedEnabled)
++        model_moveDisplaced_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with move displaced", "shouldn't have been animated with move displaced");
++    else
++        QCOMPARE(model_moveDisplaced_transitionVia.count(), 0);
++    if (change.type == ListChange::Removed && useRemoveDisplaced && removeDisplacedEnabled)
++        model_removeDisplaced_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with remove displaced", "shouldn't have been animated with remove displaced");
++    else
++        QCOMPARE(model_removeDisplaced_transitionVia.count(), 0);
++
++    if (useDisplaced && displacedEnabled
++            && ( (change.type == ListChange::Inserted && (!useAddDisplaced || !addDisplacedEnabled))
++                 || (change.type == ListChange::Moved && (!useMoveDisplaced || !moveDisplacedEnabled))
++                 || (change.type == ListChange::Removed && (!useRemoveDisplaced || !removeDisplacedEnabled))) ) {
++        model_displaced_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with generic displaced", "shouldn't have been animated with generic displaced");
++    } else {
++        QCOMPARE(model_displaced_transitionVia.count(), 0);
++    }
++
++    // verify all items moved to the correct final positions
++    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
++    for (int i=0; i < model.count() && i < items.count(); ++i) {
++        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
++        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
++        QCOMPARE(item->x(), (i%3)*80.0);
++        QCOMPARE(item->y(), (i/3)*60.0);
++        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
++        QVERIFY(name != 0);
++        QTRY_COMPARE(name->text(), model.name(i));
++    }
++
++    delete canvas;
++}
++
++void tst_QQuickGridView::displacedTransitions_data()
++{
++    QTest::addColumn<bool>("useDisplaced");
++    QTest::addColumn<bool>("displacedEnabled");
++    QTest::addColumn<bool>("useAddDisplaced");
++    QTest::addColumn<bool>("addDisplacedEnabled");
++    QTest::addColumn<bool>("useMoveDisplaced");
++    QTest::addColumn<bool>("moveDisplacedEnabled");
++    QTest::addColumn<bool>("useRemoveDisplaced");
++    QTest::addColumn<bool>("removeDisplacedEnabled");
++    QTest::addColumn<ListChange>("change");
++    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
++
++    QTest::newRow("no displaced transitions at all")
++            << false << false
++            << false << false
++            << false << false
++            << false << false
++            << ListChange::insert(0, 1) << ListRange(0, 17);
++
++    QTest::newRow("just displaced")
++            << true << true
++            << false << false
++            << false << false
++            << false << false
++            << ListChange::insert(0, 1) << ListRange(0, 17);
++
++    QTest::newRow("just displaced (not enabled)")
++            << true << false
++            << false << false
++            << false << false
++            << false << false
++            << ListChange::insert(0, 1) << ListRange(0, 17);
++
++    QTest::newRow("displaced + addDisplaced")
++            << true << true
++            << true << true
++            << false << false
++            << false << false
++            << ListChange::insert(0, 1) << ListRange(0, 17);
++
++    QTest::newRow("displaced + addDisplaced (not enabled)")
++            << true << true
++            << true << false
++            << false << false
++            << false << false
++            << ListChange::insert(0, 1) << ListRange(0, 17);
++
++    QTest::newRow("displaced + moveDisplaced")
++            << true << true
++            << false << false
++            << true << true
++            << false << false
++            << ListChange::move(0, 10, 1) << ListRange(1, 10);
++
++    QTest::newRow("displaced + moveDisplaced (not enabled)")
++            << true << true
++            << false << false
++            << true << false
++            << false << false
++            << ListChange::move(0, 10, 1) << ListRange(1, 10);
++
++    QTest::newRow("displaced + removeDisplaced")
++            << true << true
++            << false << false
++            << false << false
++            << true << true
++            << ListChange::remove(0, 1) << ListRange(1, 18);
++
++    QTest::newRow("displaced + removeDisplaced (not enabled)")
++            << true << true
++            << false << false
++            << false << false
++            << true << false
++            << ListChange::remove(0, 1) << ListRange(1, 18);
++
++
++    QTest::newRow("displaced + add, should use generic displaced for a remove")
++            << true << true
++            << true << true
++            << false << false
++            << true << false
++            << ListChange::remove(0, 1) << ListRange(1, 18);
++}
++
 +void tst_QQuickGridView::multipleTransitions()
 +{
 +    // Tests that if you interrupt a transition in progress with another action that
 +    // cancels the previous transition, the resulting items are still placed correctly.
 +
 +    QFETCH(int, initialCount);
 +    QFETCH(qreal, contentY);
 +    QFETCH(QList<ListChange>, changes);
++    QFETCH(bool, rippleAddDisplaced);
 +
 +    // add transitions on the left, moves on the right
 +    QPointF addTargets_transitionFrom(-50, -50);
 +    QPointF addDisplaced_transitionFrom(-50, 50);
 +    QPointF moveTargets_transitionFrom(50, -50);
 +    QPointF moveDisplaced_transitionFrom(50, 50);
++    QPointF removeTargets_transitionTo(-100, 300);
++    QPointF removeDisplaced_transitionFrom(100, 300);
 +
 +    QmlListModel model;
 +    for (int i = 0; i < initialCount; i++)
 +        model.addItem("Original item" + QString::number(i), "");
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("addTargets_transitionFrom", addTargets_transitionFrom);
 +    ctxt->setContextProperty("addDisplaced_transitionFrom", addDisplaced_transitionFrom);
 +    ctxt->setContextProperty("moveTargets_transitionFrom", moveTargets_transitionFrom);
 +    ctxt->setContextProperty("moveDisplaced_transitionFrom", moveDisplaced_transitionFrom);
++    ctxt->setContextProperty("removeTargets_transitionTo", removeTargets_transitionTo);
++    ctxt->setContextProperty("removeDisplaced_transitionFrom", removeDisplaced_transitionFrom);
++    ctxt->setContextProperty("rippleAddDisplaced", rippleAddDisplaced);
 +    canvas->setSource(testFileUrl("multipleTransitions.qml"));
 +    canvas->show();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QTRY_VERIFY(gridview != 0);
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +
++    if (contentY != 0) {
++        gridview->setContentY(contentY);
++        QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
++    }
++
 +    int timeBetweenActions = canvas->rootObject()->property("timeBetweenActions").toInt();
 +
 +    QList<QPair<QString, QString> > targetItems;
 +    for (int i=0; i<changes.count(); i++) {
 +        switch (changes[i].type) {
 +            case ListChange::Inserted:
 +            {
 +                for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
 +                    targetItems << qMakePair(QString("new item %1").arg(j), QString::number(j));
 +                model.insertItems(changes[i].index, targetItems);
 +                QTRY_COMPARE(model.count(), gridview->count());
 +                QTRY_VERIFY(gridview->property("runningAddTargets").toBool());
 +                QTRY_VERIFY(gridview->property("runningAddDisplaced").toBool());
 +                if (i == changes.count() - 1) {
 +                    QTRY_VERIFY(!gridview->property("runningAddTargets").toBool());
 +                    QTRY_VERIFY(!gridview->property("runningAddDisplaced").toBool());
 +                } else {
 +                    QTest::qWait(timeBetweenActions);
 +                }
 +                break;
 +            }
 +            case ListChange::Removed:
 +                for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
 +                    targetItems << qMakePair(model.name(i), model.number(i));
 +                model.removeItems(changes[i].index, changes[i].count);
 +                QTRY_COMPARE(model.count(), gridview->count());
 +                QTRY_VERIFY(gridview->property("runningRemoveTargets").toBool());
 +                QTRY_VERIFY(gridview->property("runningRemoveDisplaced").toBool());
 +                if (i == changes.count() - 1) {
 +                    QTRY_VERIFY(!gridview->property("runningRemoveTargets").toBool());
 +                    QTRY_VERIFY(!gridview->property("runningRemoveDisplaced").toBool());
 +                } else {
 +                    QTest::qWait(timeBetweenActions);
 +                }
 +                break;
 +            case ListChange::Moved:
 +                for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
 +                    targetItems << qMakePair(model.name(i), model.number(i));
 +                model.moveItems(changes[i].index, changes[i].to, changes[i].count);
 +                QTRY_VERIFY(gridview->property("runningMoveTargets").toBool());
 +                QTRY_VERIFY(gridview->property("runningMoveDisplaced").toBool());
 +                if (i == changes.count() - 1) {
 +                    QTRY_VERIFY(!gridview->property("runningMoveTargets").toBool());
 +                    QTRY_VERIFY(!gridview->property("runningMoveDisplaced").toBool());
 +                } else {
 +                    QTest::qWait(timeBetweenActions);
 +                }
 +                break;
 +            case ListChange::SetCurrent:
 +                gridview->setCurrentIndex(changes[i].index);
 +                QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +                break;
 +            case ListChange::SetContentY:
 +                gridview->setContentY(changes[i].pos);
 +                QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
 +                break;
 +        }
 +    }
 +    QCOMPARE(gridview->count(), model.count());
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    int firstVisibleIndex = -1;
 +    for (int i=0; i<items.count(); i++) {
 +        if (items[i]->y() >= contentY) {
 +            QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +            firstVisibleIndex = e.evaluate().toInt();
 +            break;
 +        }
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // verify all items moved to the correct final positions
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), (i%3)*80.0);
 +        QCOMPARE(item->y(), (i/3)*60.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::multipleTransitions_data()
 +{
 +    QTest::addColumn<int>("initialCount");
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<QList<ListChange> >("changes");
++    QTest::addColumn<bool>("rippleAddDisplaced");
 +
 +    // the added item and displaced items should move to final dest correctly
 +    QTest::newRow("add item, then move it immediately") << 10 << 0.0 << (QList<ListChange>()
-             );
++             << ListChange::insert(0, 1)
++             << ListChange::move(0, 3, 1)
++             )
++             << false;
 +
 +    // items affected by the add should change from move to add transition
 +    QTest::newRow("move, then insert item before the moved item") << 20 << 0.0 << (QList<ListChange>()
 +            << ListChange::move(1, 10, 3)
 +            << ListChange::insert(0, 1)
-             );
++            )
++            << false;
 +
 +    // items should be placed correctly if you trigger a transition then refill for that index
 +    QTest::newRow("add at 0, flick down, flick back to top and add at 0 again") << 20 << 0.0 << (QList<ListChange>()
 +            << ListChange::insert(0, 1)
 +            << ListChange::setContentY(160.0)
 +            << ListChange::setContentY(0.0)
 +            << ListChange::insert(0, 1)
++            )
++            << false;
++
++    QTest::newRow("insert then remove same index, with ripple effect on add displaced") << 20 << 0.0 << (QList<ListChange>()
++            << ListChange::insert(1, 1)
++            << ListChange::remove(1, 1)
++            )
++            << true;
 +}
 +
 +void tst_QQuickGridView::cacheBuffer()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 90; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testRightToLeft", QVariant(false));
 +    ctxt->setContextProperty("testTopToBottom", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("gridview1.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
 +    QVERIFY(gridview != 0);
 +
 +    QQuickItem *contentItem = gridview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QVERIFY(gridview->delegate() != 0);
 +    QVERIFY(gridview->model() != 0);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper", false).count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QTRY_COMPARE(item->x(), (i%3)*80.0);
 +        QTRY_COMPARE(item->y(), (i/3)*60.0);
 +    }
 +
 +    QQmlIncubationController controller;
 +    canvas->engine()->setIncubationController(&controller);
 +
 +    canvas->rootObject()->setProperty("cacheBuffer", 200);
 +    QTRY_VERIFY(gridview->cacheBuffer() == 200);
 +
 +    // items will be created one at a time
 +    for (int i = itemCount; i < qMin(itemCount+9,model.count()); ++i) {
 +        QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
 +        QQuickItem *item = 0;
 +        while (!item) {
 +            bool b = false;
 +            controller.incubateWhile(&b);
 +            item = findItem<QQuickItem>(gridview, "wrapper", i);
 +        }
 +    }
 +
 +    {
 +        bool b = true;
 +        controller.incubateWhile(&b);
 +    }
 +
 +    int newItemCount = 0;
 +    newItemCount = findItems<QQuickItem>(contentItem, "wrapper", false).count();
 +
 +    // Confirm items positioned correctly
 +    for (int i = 0; i < model.count() && i < newItemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY(item);
 +        QTRY_COMPARE(item->x(), (i%3)*80.0);
 +        QTRY_COMPARE(item->y(), (i/3)*60.0);
 +    }
 +
 +    // move view and confirm items in view are visible immediately and outside are created async
 +    gridview->setContentY(300);
 +
 +    for (int i = 15; i < 34; ++i) { // 34 due to staggered item creation
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY(item);
 +        QTRY_COMPARE(item->x(), (i%3)*80.0);
 +        QTRY_COMPARE(item->y(), (i/3)*60.0);
 +    }
 +
 +    QVERIFY(findItem<QQuickItem>(gridview, "wrapper", 34) == 0);
 +
 +    // ensure buffered items are created
 +    for (int i = 34; i < qMin(44,model.count()); ++i) {
 +        QQuickItem *item = 0;
 +        while (!item) {
 +            qGuiApp->processEvents(); // allow refill to happen
 +            bool b = false;
 +            controller.incubateWhile(&b);
 +            item = findItem<QQuickItem>(gridview, "wrapper", i);
 +        }
 +    }
 +
 +    {
 +        bool b = true;
 +        controller.incubateWhile(&b);
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::asynchronous()
 +{
 +    QQuickView *canvas = createView();
 +    canvas->show();
 +    QQmlIncubationController controller;
 +    canvas->engine()->setIncubationController(&controller);
 +
 +    canvas->setSource(testFile("asyncloader.qml"));
 +
 +    QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
 +    QVERIFY(rootObject);
 +
 +    QQuickGridView *gridview = 0;
 +    while (!gridview) {
 +        bool b = false;
 +        controller.incubateWhile(&b);
 +        gridview = rootObject->findChild<QQuickGridView*>("view");
 +    }
 +
 +    // items will be created one at a time
 +    for (int i = 0; i < 12; ++i) {
 +        QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
 +        QQuickItem *item = 0;
 +        while (!item) {
 +            bool b = false;
 +            controller.incubateWhile(&b);
 +            item = findItem<QQuickItem>(gridview, "wrapper", i);
 +        }
 +    }
 +
 +    {
 +        bool b = true;
 +        controller.incubateWhile(&b);
 +    }
 +
 +    // verify positioning
 +    QQuickItem *contentItem = gridview->contentItem();
 +    for (int i = 0; i < 12; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QVERIFY(item->x() == (i%3)*100);
 +        QVERIFY(item->y() == (i/3)*100);
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickGridView::unrequestedVisibility()
 +{
 +    QaimModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), QString::number(i));
 +
 +    QQuickView *canvas = new QQuickView(0);
 +    canvas->setGeometry(0,0,240,320);
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testWrap", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("unrequestedItems.qml"));
 +
 +    canvas->show();
 +
 +    qApp->processEvents();
 +
 +    QQuickGridView *leftview = findItem<QQuickGridView>(canvas->rootObject(), "leftGrid");
 +    QTRY_VERIFY(leftview != 0);
 +
 +    QQuickGridView *rightview = findItem<QQuickGridView>(canvas->rootObject(), "rightGrid");
 +    QTRY_VERIFY(rightview != 0);
 +
 +    QQuickItem *leftContent = leftview->contentItem();
 +    QTRY_VERIFY(leftContent != 0);
 +
 +    QQuickItem *rightContent = rightview->contentItem();
 +    QTRY_VERIFY(rightContent != 0);
 +
 +    rightview->setCurrentIndex(12);
 +
 +    QTRY_COMPARE(leftview->contentY(), 0.0);
 +    QTRY_COMPARE(rightview->contentY(), 240.0);
 +
 +    QQuickItem *item;
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
 +    QCOMPARE(item->isVisible(), true);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 9));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 10));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 3));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 4));
 +    QCOMPARE(item->isVisible(), true);
 +
 +    rightview->setCurrentIndex(0);
 +
 +    QTRY_COMPARE(leftview->contentY(), 0.0);
 +    QTRY_COMPARE(rightview->contentY(), 0.0);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
 +    QTRY_COMPARE(item->isVisible(), true);
 +
 +    QVERIFY(!findItem<QQuickItem>(leftContent, "wrapper", 11));
 +    QVERIFY(!findItem<QQuickItem>(rightContent, "wrapper", 11));
 +
 +    leftview->setCurrentIndex(12);
 +
 +    QTRY_COMPARE(leftview->contentY(), 240.0);
 +    QTRY_COMPARE(rightview->contentY(), 0.0);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
 +    QTRY_COMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), true);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    // move a non-visible item into view
 +    model.moveItems(10, 9, 1);
 +    QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
 +
 +    QTRY_VERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), true);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    // move a visible item out of view
 +    model.moveItems(5, 3, 1);
 +    QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    // move a non-visible item into view
 +    model.moveItems(3, 5, 1);
 +    QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    // move a visible item out of view
 +    model.moveItems(9, 10, 1);
 +    QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    // move a non-visible item into view
 +    model.moveItems(10, 9, 1);
 +    QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    delete canvas;
 +}
 +
 +QList<int> tst_QQuickGridView::toIntList(const QVariantList &list)
 +{
 +    QList<int> ret;
 +    bool ok = true;
 +    for (int i=0; i<list.count(); i++) {
 +        ret << list[i].toInt(&ok);
 +        if (!ok)
 +            qWarning() << "tst_QQuickGridView::toIntList(): not a number:" << list[i];
 +    }
 +
 +    return ret;
 +}
 +
 +void tst_QQuickGridView::matchIndexLists(const QVariantList &indexLists, const QList<int> &expectedIndexes)
 +{
 +    for (int i=0; i<indexLists.count(); i++) {
 +        QSet<int> current = indexLists[i].value<QList<int> >().toSet();
 +        if (current != expectedIndexes.toSet())
 +            qDebug() << "Cannot match actual targets" << current << "with expected" << expectedIndexes;
 +        QCOMPARE(current, expectedIndexes.toSet());
 +    }
 +}
 +
 +void tst_QQuickGridView::matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList<int> &expectedIndexes)
 +{
 +    for (QVariantMap::const_iterator it = items.begin(); it != items.end(); ++it) {
 +        QVERIFY(it.value().type() == QVariant::Int);
 +        QString name = it.key();
 +        int itemIndex = it.value().toInt();
 +        QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex)));
 +        if (model.name(itemIndex) != name)
 +            qDebug() << itemIndex;
 +        QCOMPARE(model.name(itemIndex), name);
 +    }
 +    QCOMPARE(items.count(), expectedIndexes.count());
 +}
 +
 +void tst_QQuickGridView::matchItemLists(const QVariantList &itemLists, const QList<QQuickItem *> &expectedItems)
 +{
 +    for (int i=0; i<itemLists.count(); i++) {
 +        QVariantList current = itemLists[i].toList();
 +        for (int j=0; j<current.count(); j++) {
 +            QQuickItem *o = qobject_cast<QQuickItem*>(current[j].value<QObject*>());
 +            QVERIFY2(o, QTest::toString(QString("Invalid actual item at %1").arg(j)));
 +            QVERIFY2(expectedItems.contains(o), QTest::toString(QString("Cannot match item %1").arg(j)));
 +        }
 +        QCOMPARE(current.count(), expectedItems.count());
 +    }
 +}
 +
 +QTEST_MAIN(tst_QQuickGridView)
 +
 +#include "tst_qquickgridview.moc"
 +
index bcac591,0000000..9195aab
mode 100644,000000..100644
--- /dev/null
@@@ -1,5716 -1,0 +1,5997 @@@
- #include <QtQuick/private/qquickchangeset_p.h>
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include <QtTest/QtTest>
 +#include <QtCore/QStringListModel>
 +#include <QtQuick/qquickview.h>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcontext.h>
 +#include <QtQml/qqmlexpression.h>
 +#include <QtQml/qqmlincubator.h>
 +#include <QtQuick/private/qquickitem_p.h>
 +#include <QtQuick/private/qquicklistview_p.h>
 +#include <QtQuick/private/qquicktext_p.h>
 +#include <QtQuick/private/qquickvisualitemmodel_p.h>
 +#include <QtQml/private/qquicklistmodel_p.h>
-     for (int i = 0; i < 3; ++i) {
-         QQuickItem *item = findItem<QQuickItem>(contentItem,
-                 "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
 +#include "../../shared/util.h"
 +#include "../shared/viewtestutil.h"
 +#include "../shared/visualtestutil.h"
 +#include "incrementalmodel.h"
 +#include <math.h>
 +
 +Q_DECLARE_METATYPE(Qt::LayoutDirection)
 +Q_DECLARE_METATYPE(QQuickListView::Orientation)
 +
 +using namespace QQuickViewTestUtil;
 +using namespace QQuickVisualTestUtil;
 +
 +class tst_QQuickListView : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_QQuickListView();
 +
 +private slots:
 +    // Test both QListModelInterface and QAbstractItemModel model types
 +    void qListModelInterface_items();
 +    void qListModelInterface_package_items();
 +    void qAbstractItemModel_items();
 +
 +    void qListModelInterface_changed();
 +    void qListModelInterface_package_changed();
 +    void qAbstractItemModel_changed();
 +
 +    void qListModelInterface_inserted();
 +    void qListModelInterface_inserted_more();
 +    void qListModelInterface_inserted_more_data();
 +    void qListModelInterface_package_inserted();
 +    void qAbstractItemModel_inserted();
 +    void qAbstractItemModel_inserted_more();
 +    void qAbstractItemModel_inserted_more_data();
 +
 +    void qListModelInterface_removed();
 +    void qListModelInterface_removed_more();
 +    void qListModelInterface_removed_more_data();
 +    void qListModelInterface_package_removed();
 +    void qAbstractItemModel_removed();
 +    void qAbstractItemModel_removed_more();
 +    void qAbstractItemModel_removed_more_data();
 +
 +    void qListModelInterface_moved();
 +    void qListModelInterface_moved_data();
 +    void qListModelInterface_package_moved();
 +    void qListModelInterface_package_moved_data();
 +    void qAbstractItemModel_moved();
 +    void qAbstractItemModel_moved_data();
 +
 +    void multipleChanges();
 +    void multipleChanges_data();
 +
 +    void qListModelInterface_clear();
 +    void qListModelInterface_package_clear();
 +    void qAbstractItemModel_clear();
 +
 +    void insertBeforeVisible();
 +    void insertBeforeVisible_data();
 +    void swapWithFirstItem();
 +    void itemList();
 +    void currentIndex_delayedItemCreation();
 +    void currentIndex_delayedItemCreation_data();
 +    void currentIndex();
 +    void noCurrentIndex();
 +    void enforceRange();
 +    void enforceRange_withoutHighlight();
 +    void spacing();
 +    void qListModelInterface_sections();
 +    void qListModelInterface_package_sections();
 +    void qAbstractItemModel_sections();
 +    void sectionsPositioning();
 +    void sectionsDelegate();
++    void sectionPropertyChange();
 +    void cacheBuffer();
 +    void positionViewAtIndex();
 +    void resetModel();
 +    void propertyChanges();
 +    void componentChanges();
 +    void modelChanges();
 +    void manualHighlight();
 +    void header();
 +    void header_data();
 +    void header_delayItemCreation();
 +    void footer();
 +    void footer_data();
 +    void headerFooter();
 +    void resizeView();
 +    void resizeViewAndRepaint();
 +    void sizeLessThan1();
 +    void QTBUG_14821();
 +    void resizeDelegate();
 +    void resizeFirstDelegate();
 +    void QTBUG_16037();
 +    void indexAt_itemAt_data();
 +    void indexAt_itemAt();
 +    void incrementalModel();
 +    void onAdd();
 +    void onAdd_data();
 +    void onRemove();
 +    void onRemove_data();
 +    void rightToLeft();
 +    void test_mirroring();
 +    void margins();
 +    void marginsResize();
 +    void marginsResize_data();
 +    void creationContext();
 +    void snapToItem_data();
 +    void snapToItem();
 +    void snapOneItem_data();
 +    void snapOneItem();
 +
 +    void QTBUG_9791();
 +    void QTBUG_11105();
 +    void QTBUG_21742();
 +
 +    void asynchronous();
 +    void unrequestedVisibility();
 +
 +    void populateTransitions();
 +    void populateTransitions_data();
 +    void addTransitions();
 +    void addTransitions_data();
 +    void moveTransitions();
 +    void moveTransitions_data();
 +    void removeTransitions();
 +    void removeTransitions_data();
++    void displacedTransitions();
++    void displacedTransitions_data();
 +    void multipleTransitions();
 +    void multipleTransitions_data();
 +
 +private:
 +    template <class T> void items(const QUrl &source, bool forceLayout);
 +    template <class T> void changed(const QUrl &source, bool forceLayout);
 +    template <class T> void inserted(const QUrl &source);
 +    template <class T> void inserted_more();
 +    template <class T> void removed(const QUrl &source, bool animated);
 +    template <class T> void removed_more(const QUrl &source);
 +    template <class T> void moved(const QUrl &source);
 +    template <class T> void clear(const QUrl &source);
 +    template <class T> void sections(const QUrl &source);
 +
 +    QList<int> toIntList(const QVariantList &list);
 +    void matchIndexLists(const QVariantList &indexLists, const QList<int> &expectedIndexes);
 +    void matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList<int> &expectedIndexes);
 +    void matchItemLists(const QVariantList &itemLists, const QList<QQuickItem *> &expectedItems);
 +
 +    void inserted_more_data();
 +    void removed_more_data();
 +    void moved_data();
 +};
 +
 +class TestObject : public QObject
 +{
 +    Q_OBJECT
 +
 +    Q_PROPERTY(bool error READ error WRITE setError NOTIFY changedError)
 +    Q_PROPERTY(bool animate READ animate NOTIFY changedAnim)
 +    Q_PROPERTY(bool invalidHighlight READ invalidHighlight NOTIFY changedHl)
 +    Q_PROPERTY(int cacheBuffer READ cacheBuffer NOTIFY changedCacheBuffer)
 +
 +public:
 +    TestObject(QObject *parent = 0)
 +        : QObject(parent), mError(true), mAnimate(false), mInvalidHighlight(false)
 +        , mCacheBuffer(0) {}
 +
 +    bool error() const { return mError; }
 +    void setError(bool err) { mError = err; emit changedError(); }
 +
 +    bool animate() const { return mAnimate; }
 +    void setAnimate(bool anim) { mAnimate = anim; emit changedAnim(); }
 +
 +    bool invalidHighlight() const { return mInvalidHighlight; }
 +    void setInvalidHighlight(bool invalid) { mInvalidHighlight = invalid; emit changedHl(); }
 +
 +    int cacheBuffer() const { return mCacheBuffer; }
 +    void setCacheBuffer(int buffer) { mCacheBuffer = buffer; emit changedCacheBuffer(); }
 +
 +signals:
 +    void changedError();
 +    void changedAnim();
 +    void changedHl();
 +    void changedCacheBuffer();
 +
 +public:
 +    bool mError;
 +    bool mAnimate;
 +    bool mInvalidHighlight;
 +    int mCacheBuffer;
 +};
 +
 +tst_QQuickListView::tst_QQuickListView()
 +{
 +}
 +
 +template <class T>
 +void tst_QQuickListView::items(const QUrl &source, bool forceLayout)
 +{
 +    QQuickView *canvas = createView();
 +
 +    T model;
 +    model.addItem("Fred", "12345");
 +    model.addItem("John", "2345");
 +    model.addItem("Bob", "54321");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(source);
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
 +    QTRY_VERIFY(testObject->error() == false);
 +
 +    QTRY_VERIFY(listview->highlightItem() != 0);
 +    QTRY_COMPARE(listview->count(), model.count());
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +    QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
 +
 +    // current item should be first item
 +    QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
 +
 +    for (int i = 0; i < model.count(); ++i) {
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QTRY_VERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QTRY_VERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +
 +    // switch to other delegate
 +    testObject->setAnimate(true);
 +    QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
 +    QTRY_VERIFY(testObject->error() == false);
 +    QTRY_VERIFY(listview->currentItem());
 +
 +    // set invalid highlight
 +    testObject->setInvalidHighlight(true);
 +    QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
 +    QTRY_VERIFY(testObject->error() == false);
 +    QTRY_VERIFY(listview->currentItem());
 +    QTRY_VERIFY(listview->highlightItem() == 0);
 +
 +    // back to normal highlight
 +    testObject->setInvalidHighlight(false);
 +    QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
 +    QTRY_VERIFY(testObject->error() == false);
 +    QTRY_VERIFY(listview->currentItem());
 +    QTRY_VERIFY(listview->highlightItem() != 0);
 +
 +    // set an empty model and confirm that items are destroyed
 +    T model2;
 +    ctxt->setContextProperty("testModel", &model2);
 +
 +    // Force a layout, necessary if ListView is completed before VisualDataModel.
 +    if (forceLayout)
 +        QCOMPARE(listview->property("count").toInt(), 0);
 +
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    QTRY_VERIFY(itemCount == 0);
 +
 +    QTRY_COMPARE(listview->highlightResizeSpeed(), 1000.0);
 +    QTRY_COMPARE(listview->highlightMoveSpeed(), 1000.0);
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +
 +template <class T>
 +void tst_QQuickListView::changed(const QUrl &source, bool forceLayout)
 +{
 +    QQuickView *canvas = createView();
 +
 +    T model;
 +    model.addItem("Fred", "12345");
 +    model.addItem("John", "2345");
 +    model.addItem("Bob", "54321");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(source);
 +    qApp->processEvents();
 +
 +    QQuickFlickable *listview = findItem<QQuickFlickable>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    // Force a layout, necessary if ListView is completed before VisualDataModel.
 +    if (forceLayout)
 +        QCOMPARE(listview->property("count").toInt(), model.count());
 +
 +    model.modifyItem(1, "Will", "9876");
 +    QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(1));
 +    QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(1));
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +template <class T>
 +void tst_QQuickListView::inserted(const QUrl &source)
 +{
 +    QQuickView *canvas = createView();
 +    canvas->show();
 +
 +    T model;
 +    model.addItem("Fred", "12345");
 +    model.addItem("John", "2345");
 +    model.addItem("Bob", "54321");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(source);
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    model.insertItem(1, "Will", "9876");
 +
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +    QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
 +
 +    QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(1));
 +    QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(1));
 +
 +    // Confirm items positioned correctly
 +    for (int i = 0; i < model.count(); ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QTRY_COMPARE(item->y(), i*20.0);
 +    }
 +
 +    model.insertItem(0, "Foo", "1111"); // zero index, and current item
 +
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +    QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
 +
 +    name = findItem<QQuickText>(contentItem, "textName", 0);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(0));
 +    number = findItem<QQuickText>(contentItem, "textNumber", 0);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(0));
 +
 +    QTRY_COMPARE(listview->currentIndex(), 1);
 +
 +    // Confirm items positioned correctly
 +    for (int i = 0; i < model.count(); ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QTRY_COMPARE(item->y(), i*20.0);
 +    }
 +
 +    for (int i = model.count(); i < 30; ++i)
 +        model.insertItem(i, "Hello", QString::number(i));
 +
 +    listview->setContentY(80);
 +
 +    // Insert item outside visible area
 +    model.insertItem(1, "Hello", "1324");
 +
 +    QTRY_VERIFY(listview->contentY() == 80);
 +
 +    // Confirm items positioned correctly
 +    for (int i = 5; i < 5+15; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.0 - 20.0);
 +    }
 +
 +//    QTRY_COMPARE(listview->contentItemHeight(), model.count() * 20.0);
 +
 +    // QTBUG-19675
 +    model.clear();
 +    model.insertItem(0, "Hello", "1234");
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item);
 +    QCOMPARE(item->y(), 0.);
 +    QTRY_VERIFY(listview->contentY() == 0);
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +template <class T>
 +void tst_QQuickListView::inserted_more()
 +{
 +    QFETCH(qreal, contentY);
 +    QFETCH(int, insertIndex);
 +    QFETCH(int, insertCount);
 +    QFETCH(qreal, itemsOffsetAfterMove);
 +
 +    T model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    canvas->show();
 +    qApp->processEvents();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    listview->setContentY(contentY);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QList<QPair<QString, QString> > newData;
 +    for (int i=0; i<insertCount; i++)
 +        newData << qMakePair(QString("value %1").arg(i), QString::number(i));
 +    model.insertItems(insertIndex, newData);
 +    QTRY_COMPARE(listview->property("count").toInt(), model.count());
 +
 +    // check visibleItems.first() is in correct position
 +    QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item0);
 +    QCOMPARE(item0->y(), itemsOffsetAfterMove);
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    int firstVisibleIndex = -1;
 +    for (int i=0; i<items.count(); i++) {
 +        if (items[i]->y() >= contentY) {
 +            QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +            firstVisibleIndex = e.evaluate().toInt();
 +            break;
 +        }
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // Confirm items positioned correctly and indexes correct
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    QQuickText *name;
 +    QQuickText *number;
 +    for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QVERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::inserted_more_data()
 +{
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<int>("insertIndex");
 +    QTest::addColumn<int>("insertCount");
 +    QTest::addColumn<qreal>("itemsOffsetAfterMove");
 +
 +    QTest::newRow("add 1, before visible items")
 +            << 80.0     // show 4-19
 +            << 3 << 1
 +            << -20.0;   // insert above first visible i.e. 0 is at -20, first visible should not move
 +
 +    QTest::newRow("add multiple, before visible")
 +            << 80.0     // show 4-19
 +            << 3 << 3
 +            << -20.0 * 3;   // again first visible should not move
 +
 +    QTest::newRow("add 1, at start of visible, content at start")
 +            << 0.0
 +            << 0 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add multiple, start of visible, content at start")
 +            << 0.0
 +            << 0 << 3
 +            << 0.0;
 +
 +    QTest::newRow("add 1, at start of visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 4 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add multiple, at start of visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 4 << 3
 +            << 0.0;
 +
 +
 +    QTest::newRow("add 1, at end of visible, content at start")
 +            << 0.0
 +            << 15 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add 1, at end of visible, content at start")
 +            << 0.0
 +            << 15 << 3
 +            << 0.0;
 +
 +    QTest::newRow("add 1, at end of visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 19 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add multiple, at end of visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 19 << 3
 +            << 0.0;
 +
 +
 +    QTest::newRow("add 1, after visible, content at start")
 +            << 0.0
 +            << 16 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add 1, after visible, content at start")
 +            << 0.0
 +            << 16 << 3
 +            << 0.0;
 +
 +    QTest::newRow("add 1, after visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 20 << 1
 +            << 0.0;
 +
 +    QTest::newRow("add multiple, after visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 20 << 3
 +            << 0.0;
 +}
 +
 +void tst_QQuickListView::insertBeforeVisible()
 +{
 +    QFETCH(int, insertIndex);
 +    QFETCH(int, insertCount);
 +    QFETCH(int, cacheBuffer);
 +
 +    QQuickText *name;
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    canvas->show();
 +    qApp->processEvents();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    listview->setCacheBuffer(cacheBuffer);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // trigger a refill (not just setting contentY) so that the visibleItems grid is updated
 +    int firstVisibleIndex = 20;     // move to an index where the top item is not visible
 +    listview->setContentY(firstVisibleIndex * 20.0);
 +    listview->setCurrentIndex(firstVisibleIndex);
 +
 +    qApp->processEvents();
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    QTRY_COMPARE(listview->currentIndex(), firstVisibleIndex);
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex);
 +    QVERIFY(item);
 +    QCOMPARE(item->y(), listview->contentY());
 +
 +    QList<QPair<QString, QString> > newData;
 +    for (int i=0; i<insertCount; i++)
 +        newData << qMakePair(QString("value %1").arg(i), QString::number(i));
 +    model.insertItems(insertIndex, newData);
 +    QTRY_COMPARE(listview->property("count").toInt(), model.count());
 +
 +    // now, moving to the top of the view should position the inserted items correctly
 +    int itemsOffsetAfterMove = -(insertCount * 20);
 +    listview->setCurrentIndex(0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    QTRY_COMPARE(listview->currentIndex(), 0);
 +    QTRY_COMPARE(listview->contentY(), 0.0 + itemsOffsetAfterMove);
 +
 +    // Confirm items positioned correctly and indexes correct
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::insertBeforeVisible_data()
 +{
 +    QTest::addColumn<int>("insertIndex");
 +    QTest::addColumn<int>("insertCount");
 +    QTest::addColumn<int>("cacheBuffer");
 +
 +    QTest::newRow("insert 1 at 0, 0 buffer") << 0 << 1 << 0;
 +    QTest::newRow("insert 1 at 0, 100 buffer") << 0 << 1 << 100;
 +    QTest::newRow("insert 1 at 0, 500 buffer") << 0 << 1 << 500;
 +
 +    QTest::newRow("insert 1 at 1, 0 buffer") << 1 << 1 << 0;
 +    QTest::newRow("insert 1 at 1, 100 buffer") << 1 << 1 << 100;
 +    QTest::newRow("insert 1 at 1, 500 buffer") << 1 << 1 << 500;
 +
 +    QTest::newRow("insert multiple at 0, 0 buffer") << 0 << 3 << 0;
 +    QTest::newRow("insert multiple at 0, 100 buffer") << 0 << 3 << 100;
 +    QTest::newRow("insert multiple at 0, 500 buffer") << 0 << 3 << 500;
 +
 +    QTest::newRow("insert multiple at 1, 0 buffer") << 1 << 3 << 0;
 +    QTest::newRow("insert multiple at 1, 100 buffer") << 1 << 3 << 100;
 +    QTest::newRow("insert multiple at 1, 500 buffer") << 1 << 3 << 500;
 +}
 +
 +template <class T>
 +void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
 +{
 +    QQuickView *canvas = createView();
 +
 +    T model;
 +    for (int i = 0; i < 50; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(source);
 +    canvas->show();
 +    qApp->processEvents();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    model.removeItem(1);
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(1));
 +    QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(1));
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_VERIFY(item->y() == i*20);
 +    }
 +
 +    // Remove first item (which is the current item);
 +    model.removeItem(0);
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    name = findItem<QQuickText>(contentItem, "textName", 0);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(0));
 +    number = findItem<QQuickText>(contentItem, "textNumber", 0);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(0));
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(),i*20.0);
 +    }
 +
 +    // Remove items not visible
 +    model.removeItem(18);
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(),i*20.0);
 +    }
 +
 +    // Remove items before visible
 +    listview->setContentY(80);
 +    listview->setCurrentIndex(10);
 +
 +    model.removeItem(1); // post: top item will be at 20
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    // Confirm items positioned correctly
 +    for (int i = 2; i < 18; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(),20+i*20.0);
 +    }
 +
 +    // Remove current index
 +    QTRY_VERIFY(listview->currentIndex() == 9);
 +    QQuickItem *oldCurrent = listview->currentItem();
 +    model.removeItem(9);
 +
 +    QTRY_COMPARE(listview->currentIndex(), 9);
 +    QTRY_VERIFY(listview->currentItem() != oldCurrent);
 +
 +    listview->setContentY(20); // That's the top now
 +    // let transitions settle.
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    QTest::qWait(300);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(),20+i*20.0);
 +    }
 +
 +    // remove current item beyond visible items.
 +    listview->setCurrentIndex(20);
 +    listview->setContentY(40);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    model.removeItem(20);
 +    QTRY_COMPARE(listview->currentIndex(), 20);
 +    QTRY_VERIFY(listview->currentItem() != 0);
 +
 +    // remove item before current, but visible
 +    listview->setCurrentIndex(8);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    oldCurrent = listview->currentItem();
 +    model.removeItem(6);
 +
 +    QTRY_COMPARE(listview->currentIndex(), 7);
 +    QTRY_VERIFY(listview->currentItem() == oldCurrent);
 +
 +    listview->setContentY(80);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    QTest::qWait(300);
 +
 +    // remove all visible items
 +    model.removeItems(1, 18);
 +    QTRY_COMPARE(listview->count() , model.count());
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i+1);
 +        if (!item) qWarning() << "Item" << i+1 << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(),80+i*20.0);
 +    }
 +
 +    model.removeItems(1, 17);
 +    QTRY_COMPARE(listview->count() , model.count());
 +
 +    model.removeItems(2, 1);
 +    QTRY_COMPARE(listview->count() , model.count());
 +
 +    model.addItem("New", "1");
 +    QTRY_COMPARE(listview->count() , model.count());
 +
 +    QTRY_VERIFY(name = findItem<QQuickText>(contentItem, "textName", model.count()-1));
 +    QCOMPARE(name->text(), QString("New"));
 +
 +    // Add some more items so that we don't run out
 +    model.clear();
 +    for (int i = 0; i < 50; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    // QTBUG-QTBUG-20575
 +    listview->setCurrentIndex(0);
 +    listview->setContentY(30);
 +    model.removeItem(0);
 +    QTRY_VERIFY(name = findItem<QQuickText>(contentItem, "textName", 0));
 +
 +    // QTBUG-19198 move to end and remove all visible items one at a time.
 +    listview->positionViewAtEnd();
 +    for (int i = 0; i < 18; ++i)
 +        model.removeItems(model.count() - 1, 1);
 +    QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() > 16);
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +template <class T>
 +void tst_QQuickListView::removed_more(const QUrl &source)
 +{
 +    QFETCH(qreal, contentY);
 +    QFETCH(int, removeIndex);
 +    QFETCH(int, removeCount);
 +    QFETCH(qreal, itemsOffsetAfterMove);
 +
 +    QQuickText *name;
 +    QQuickText *number;
 +    QQuickView *canvas = createView();
 +
 +    T model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(source);
 +    canvas->show();
 +    qApp->processEvents();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    listview->setContentY(contentY);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // wait for refill (after refill, items above the firstVisibleIndex-1 should not be rendered)
 +    int firstVisibleIndex = contentY / 20;
 +    if (firstVisibleIndex - 2 >= 0)
 +        QTRY_VERIFY(!findItem<QQuickText>(contentItem, "textName", firstVisibleIndex - 2));
 +
 +    model.removeItems(removeIndex, removeCount);
 +    QTRY_COMPARE(listview->property("count").toInt(), model.count());
 +
 +    // check visibleItems.first() is in correct position
 +    QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item0);
 +    QCOMPARE(item0->y(), itemsOffsetAfterMove);
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    for (int i=0; i<items.count(); i++) {
 +        if (items[i]->y() >= contentY) {
 +            QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +            firstVisibleIndex = e.evaluate().toInt();
 +            break;
 +        }
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // Confirm items positioned correctly and indexes correct
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QVERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::removed_more_data()
 +{
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<int>("removeIndex");
 +    QTest::addColumn<int>("removeCount");
 +    QTest::addColumn<qreal>("itemsOffsetAfterMove");
 +
 +    QTest::newRow("remove 1, before visible items")
 +            << 80.0     // show 4-19
 +            << 3 << 1
 +            << 20.0;   // visible items slide down by 1 item so that first visible does not move
 +
 +    QTest::newRow("remove multiple, all before visible items")
 +            << 80.0
 +            << 1 << 3
 +            << 20.0 * 3;
 +
 +    QTest::newRow("remove multiple, all before visible items, remove item 0")
 +            << 80.0
 +            << 0 << 4
 +            << 20.0 * 4;
 +
 +    // remove 1,2,3 before the visible pos, 0 moves down to just before the visible pos,
 +    // items 4,5 are removed from view, item 6 slides up to original pos of item 4 (80px)
 +    QTest::newRow("remove multiple, mix of items from before and within visible items")
 +            << 80.0
 +            << 1 << 5
 +            << 20.0 * 3;    // adjust for the 3 items removed before the visible
 +
 +    QTest::newRow("remove multiple, mix of items from before and within visible items, remove item 0")
 +            << 80.0
 +            << 0 << 6
 +            << 20.0 * 4;    // adjust for the 3 items removed before the visible
 +
 +
 +    QTest::newRow("remove 1, from start of visible, content at start")
 +            << 0.0
 +            << 0 << 1
 +            << 0.0;
 +
 +    QTest::newRow("remove multiple, from start of visible, content at start")
 +            << 0.0
 +            << 0 << 3
 +            << 0.0;
 +
 +    QTest::newRow("remove 1, from start of visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 4 << 1
 +            << 0.0;
 +
 +    QTest::newRow("remove multiple, from start of visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 4 << 3
 +            << 0.0;
 +
 +
 +    QTest::newRow("remove 1, from middle of visible, content at start")
 +            << 0.0
 +            << 10 << 1
 +            << 0.0;
 +
 +    QTest::newRow("remove multiple, from middle of visible, content at start")
 +            << 0.0
 +            << 10 << 5
 +            << 0.0;
 +
 +    QTest::newRow("remove 1, from middle of visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 10 << 1
 +            << 0.0;
 +
 +    QTest::newRow("remove multiple, from middle of visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 10 << 5
 +            << 0.0;
 +
 +
 +    QTest::newRow("remove 1, after visible, content at start")
 +            << 0.0
 +            << 16 << 1
 +            << 0.0;
 +
 +    QTest::newRow("remove multiple, after visible, content at start")
 +            << 0.0
 +            << 16 << 5
 +            << 0.0;
 +
 +    QTest::newRow("remove 1, after visible, content not at middle")
 +            << 80.0     // show 4-19
 +            << 16+4 << 1
 +            << 0.0;
 +
 +    QTest::newRow("remove multiple, after visible, content not at start")
 +            << 80.0     // show 4-19
 +            << 16+4 << 5
 +            << 0.0;
 +
 +    QTest::newRow("remove multiple, mix of items from within and after visible items")
 +            << 80.0
 +            << 18 << 5
 +            << 0.0;
 +}
 +
 +template <class T>
 +void tst_QQuickListView::clear(const QUrl &source)
 +{
 +    QQuickView *canvas = createView();
 +
 +    T model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(source);
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    model.clear();
 +
 +    QTRY_VERIFY(listview->count() == 0);
 +    QTRY_VERIFY(listview->currentItem() == 0);
 +    QTRY_VERIFY(listview->contentY() == 0);
 +    QVERIFY(listview->currentIndex() == -1);
 +
 +    // confirm sanity when adding an item to cleared list
 +    model.addItem("New", "1");
 +    QTRY_VERIFY(listview->count() == 1);
 +    QVERIFY(listview->currentItem() != 0);
 +    QVERIFY(listview->currentIndex() == 0);
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +template <class T>
 +void tst_QQuickListView::moved(const QUrl &source)
 +{
 +    QFETCH(qreal, contentY);
 +    QFETCH(int, from);
 +    QFETCH(int, to);
 +    QFETCH(int, count);
 +    QFETCH(qreal, itemsOffsetAfterMove);
 +
 +    QQuickText *name;
 +    QQuickText *number;
 +    QQuickView *canvas = createView();
 +
 +    T model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(source);
 +    canvas->show();
 +    qApp->processEvents();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QQuickItem *currentItem = listview->currentItem();
 +    QTRY_VERIFY(currentItem != 0);
 +
 +    if (contentY != 0) {
 +        listview->setContentY(contentY);
 +        QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    }
 +
 +    model.moveItems(from, to, count);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    int firstVisibleIndex = -1;
 +    for (int i=0; i<items.count(); i++) {
 +        if (items[i]->y() >= contentY) {
 +            QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +            firstVisibleIndex = e.evaluate().toInt();
 +            break;
 +        }
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // Confirm items positioned correctly and indexes correct
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        if (i >= firstVisibleIndex + 16)    // index has moved out of view
 +            continue;
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QVERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +
 +        // current index should have been updated
 +        if (item == currentItem)
 +            QTRY_COMPARE(listview->currentIndex(), i);
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::moved_data()
 +{
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<int>("from");
 +    QTest::addColumn<int>("to");
 +    QTest::addColumn<int>("count");
 +    QTest::addColumn<qreal>("itemsOffsetAfterMove");
 +
 +    // model starts with 30 items, each 20px high, in area 320px high
 +    // 16 items should be visible at a time
 +    // itemsOffsetAfterMove should be > 0 whenever items above the visible pos have moved
 +
 +    QTest::newRow("move 1 forwards, within visible items")
 +            << 0.0
 +            << 1 << 4 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 forwards, from non-visible -> visible")
 +            << 80.0     // show 4-19
 +            << 1 << 18 << 1
 +            << 20.0;    // removed 1 item above the first visible, so item 0 should drop down by 1 to minimize movement
 +
 +    QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
 +            << 80.0     // show 4-19
 +            << 0 << 4 << 1
 +            << 20.0;    // first item has moved to below item4, everything drops down by size of 1 item
 +
 +    QTest::newRow("move 1 forwards, from visible -> non-visible")
 +            << 0.0
 +            << 1 << 16 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 forwards, from visible -> non-visible (move first item)")
 +            << 0.0
 +            << 0 << 16 << 1
 +            << 0.0;
 +
 +
 +    QTest::newRow("move 1 backwards, within visible items")
 +            << 0.0
 +            << 4 << 1 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 backwards, within visible items (to first index)")
 +            << 0.0
 +            << 4 << 0 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 backwards, from non-visible -> visible")
 +            << 0.0
 +            << 20 << 4 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 backwards, from non-visible -> visible (move last item)")
 +            << 0.0
 +            << 29 << 15 << 1
 +            << 0.0;
 +
 +    QTest::newRow("move 1 backwards, from visible -> non-visible")
 +            << 80.0     // show 4-19
 +            << 16 << 1 << 1
 +            << -20.0;   // to minimize movement, item 0 moves to -20, and other items do not move
 +
 +    QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
 +            << 80.0     // show 4-19
 +            << 16 << 0 << 1
 +            << -20.0;   // to minimize movement, item 16 (now at 0) moves to -20, and other items do not move
 +
 +
 +    QTest::newRow("move multiple forwards, within visible items")
 +            << 0.0
 +            << 0 << 5 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple forwards, before visible items")
 +            << 140.0     // show 7-22
 +            << 4 << 5 << 3      // 4,5,6 move to below 7
 +            << 20.0 * 3;      // 4,5,6 moved down
 +
 +    QTest::newRow("move multiple forwards, from non-visible -> visible")
 +            << 80.0     // show 4-19
 +            << 1 << 5 << 3
 +            << 20.0 * 3;    // moving 3 from above the content y should adjust y positions accordingly
 +
 +    QTest::newRow("move multiple forwards, from non-visible -> visible (move first item)")
 +            << 80.0     // show 4-19
 +            << 0 << 5 << 3
 +            << 20.0 * 3;        // moving 3 from above the content y should adjust y positions accordingly
 +
 +    QTest::newRow("move multiple forwards, mix of non-visible/visible")
 +            << 40.0
 +            << 1 << 16 << 2
 +            << 20.0;    // item 1,2 are removed, item 3 is now first visible
 +
 +    QTest::newRow("move multiple forwards, to bottom of view")
 +            << 0.0
 +            << 5 << 13 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple forwards, to bottom of view, first->last")
 +            << 0.0
 +            << 0 << 13 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple forwards, to bottom of view, content y not 0")
 +            << 80.0
 +            << 5+4 << 13+4 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple forwards, from visible -> non-visible")
 +            << 0.0
 +            << 1 << 16 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple forwards, from visible -> non-visible (move first item)")
 +            << 0.0
 +            << 0 << 16 << 3
 +            << 0.0;
 +
 +
 +    QTest::newRow("move multiple backwards, within visible items")
 +            << 0.0
 +            << 4 << 1 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple backwards, within visible items (move first item)")
 +            << 0.0
 +            << 10 << 0 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple backwards, from non-visible -> visible")
 +            << 0.0
 +            << 20 << 4 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple backwards, from non-visible -> visible (move last item)")
 +            << 0.0
 +            << 27 << 10 << 3
 +            << 0.0;
 +
 +    QTest::newRow("move multiple backwards, from visible -> non-visible")
 +            << 80.0     // show 4-19
 +            << 16 << 1 << 3
 +            << -20.0 * 3;   // to minimize movement, 0 moves by -60, and other items do not move
 +
 +    QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
 +            << 80.0     // show 4-19
 +            << 16 << 0 << 3
 +            << -20.0 * 3;   // to minimize movement, 16,17,18 move to above item 0, and other items do not move
 +}
 +
 +void tst_QQuickListView::multipleChanges()
 +{
 +    QFETCH(int, startCount);
 +    QFETCH(QList<ListChange>, changes);
 +    QFETCH(int, newCount);
 +    QFETCH(int, newCurrentIndex);
 +
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < startCount; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    canvas->show();
 +    qApp->processEvents();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    for (int i=0; i<changes.count(); i++) {
 +        switch (changes[i].type) {
 +            case ListChange::Inserted:
 +            {
 +                QList<QPair<QString, QString> > items;
 +                for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
 +                    items << qMakePair(QString("new item %1").arg(j), QString::number(j));
 +                model.insertItems(changes[i].index, items);
 +                QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +                break;
 +            }
 +            case ListChange::Removed:
 +                model.removeItems(changes[i].index, changes[i].count);
 +                QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +                break;
 +            case ListChange::Moved:
 +                model.moveItems(changes[i].index, changes[i].to, changes[i].count);
 +                QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +                break;
 +            case ListChange::SetCurrent:
 +                listview->setCurrentIndex(changes[i].index);
 +                QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +                break;
 +            case ListChange::SetContentY:
 +                listview->setContentY(changes[i].pos);
 +                QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +                break;
 +        }
 +    }
 +
 +    QTRY_COMPARE(listview->count(), newCount);
 +    QCOMPARE(listview->count(), model.count());
 +    QTRY_COMPARE(listview->currentIndex(), newCurrentIndex);
 +
 +    QQuickText *name;
 +    QQuickText *number;
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i=0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +        number = findItem<QQuickText>(contentItem, "textNumber", i);
 +        QVERIFY(number != 0);
 +        QTRY_COMPARE(number->text(), model.number(i));
 +    }
 +
 +    delete testObject;
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::multipleChanges_data()
 +{
 +    QTest::addColumn<int>("startCount");
 +    QTest::addColumn<QList<ListChange> >("changes");
 +    QTest::addColumn<int>("newCount");
 +    QTest::addColumn<int>("newCurrentIndex");
 +
 +    QList<ListChange> changes;
 +
 +    for (int i=1; i<30; i++)
 +        changes << ListChange::remove(0);
 +    QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
 +
 +    changes << ListChange::remove(0);
 +    QTest::newRow("remove all") << 30 << changes << 0 << -1;
 +
 +    changes.clear();
 +    changes << ListChange::setCurrent(29);
 +    for (int i=29; i>0; i--)
 +        changes << ListChange::remove(i);
 +    QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
 +
 +    QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
 +            << ListChange::remove(0, 1)
 +            << ListChange::insert(0, 1)
 +            ) << 10 << 1;
 +
 +    QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(2)
 +            << ListChange::remove(2, 1)
 +            << ListChange::insert(2, 1)
 +            ) << 10 << 3;
 +
 +    QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(1)
 +            << ListChange::remove(1, 3)
 +            << ListChange::insert(2, 2)
 +            ) << 9 << 1;
 +
 +    QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(2)
 +            << ListChange::remove(1, 3)
 +            << ListChange::move(1, 5, 1)
 +            ) << 7 << 5;
 +
 +    QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(5)
 +            << ListChange::remove(4, 3)
 +            << ListChange::move(4, 1, 1)
 +            ) << 7 << 1;
 +
 +
 +    QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
 +            << ListChange::insert(0, 2)
 +            << ListChange::insert(0, 4)
 +            << ListChange::insert(0, 6)
 +            ) << 12 << 10;
 +
 +    QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
 +            << ListChange::insert(0, 2)
 +            << ListChange::insert(0, 4)
 +            << ListChange::insert(0, 6)
 +            << ListChange::setCurrent(3)
 +            << ListChange::insert(3, 2)
 +            ) << 14 << 5;
 +
 +    QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
 +            << ListChange::insert(0, 30)
 +            << ListChange::remove(0, 30)
 +            ) << 0 << -1;
 +
 +    QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
 +            << ListChange::insert(1)
 +            << ListChange::setCurrent(1)
 +            << ListChange::remove(1)
 +            ) << 30 << 1;
 +
 +    QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
 +            << ListChange::insert(0, 10)
 +            << ListChange::remove(5, 10)
 +            ) << 10 << 5;
 +
 +    QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
 +            << ListChange::insert(0, 3)
 +            << ListChange::move(0, 10, 3)
 +            ) << 13 << 0;
 +
 +    QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
 +            << ListChange::insert(0, 3)
 +            << ListChange::move(0, 8, 5)
 +            ) << 13 << 11;
 +
 +    QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(9)
 +            << ListChange::insert(10, 3)
 +            << ListChange::move(8, 0, 5)
 +            ) << 13 << 1;
 +
 +
 +    QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(1)
 +            << ListChange::move(1, 2, 2)
 +            << ListChange::move(2, 1, 2)
 +            ) << 10 << 1;
 +
 +    QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(2)
 +            << ListChange::move(1, 2, 3)
 +            << ListChange::move(3, 0, 5)
 +            ) << 10 << 0;
 +
 +    QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(5)
 +            << ListChange::move(5, 0, 1)
 +            << ListChange::remove(0)
 +            ) << 9 << 0;
 +
 +    QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(5)
 +            << ListChange::move(5, 0, 1)
 +            << ListChange::insert(0)
 +            ) << 11 << 1;
 +
 +    QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(1)
 +            << ListChange::move(5, 1, 3)
 +            << ListChange::remove(1, 3)
 +            ) << 7 << 1;
 +
 +    QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(5)
 +            << ListChange::move(5, 1, 3)
 +            << ListChange::insert(1, 5)
 +            ) << 15 << 6;
 +
 +    QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
 +            << ListChange::setCurrent(3)
 +            << ListChange::move(0, 1, 2)
 +            << ListChange::insert(3, 5)
 +            ) << 15 << 8;
 +
 +
 +    QTest::newRow("clear current") << 0 << (QList<ListChange>()
 +            << ListChange::insert(0, 5)
 +            << ListChange::setCurrent(-1)
 +            << ListChange::remove(0, 5)
 +            << ListChange::insert(0, 5)
 +            ) << 5 << -1;
 +}
 +
 +void tst_QQuickListView::swapWithFirstItem()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // ensure content position is stable
 +    listview->setContentY(0);
 +    model.moveItem(1, 0);
 +    QTRY_VERIFY(listview->contentY() == 0);
 +
 +    delete testObject;
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::enforceRange()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("listview-enforcerange.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QTRY_COMPARE(listview->preferredHighlightBegin(), 100.0);
 +    QTRY_COMPARE(listview->preferredHighlightEnd(), 100.0);
 +    QTRY_COMPARE(listview->highlightRangeMode(), QQuickListView::StrictlyEnforceRange);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    // view should be positioned at the top of the range.
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(listview->contentY(), -100.0);
 +
 +    QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
 +    QTRY_VERIFY(name != 0);
 +    QTRY_COMPARE(name->text(), model.name(0));
 +    QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
 +    QTRY_VERIFY(number != 0);
 +    QTRY_COMPARE(number->text(), model.number(0));
 +
 +    // Check currentIndex is updated when contentItem moves
 +    listview->setContentY(20);
 +
 +    QTRY_COMPARE(listview->currentIndex(), 6);
 +
 +    // change model
 +    QmlListModel model2;
 +    for (int i = 0; i < 5; i++)
 +        model2.addItem("Item" + QString::number(i), "");
 +
 +    ctxt->setContextProperty("testModel", &model2);
 +    QCOMPARE(listview->count(), 5);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::enforceRange_withoutHighlight()
 +{
 +    // QTBUG-20287
 +    // If no highlight is set but StrictlyEnforceRange is used, the content should still move
 +    // to the correct position (i.e. to the next/previous item, not next/previous section)
 +    // when moving up/down via incrementCurrentIndex() and decrementCurrentIndex()
 +
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    model.addItem("Item 0", "a");
 +    model.addItem("Item 1", "b");
 +    model.addItem("Item 2", "b");
 +    model.addItem("Item 3", "c");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("listview-enforcerange-nohighlight.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    qreal expectedPos = -100.0;
 +
 +    expectedPos += 10.0;    // scroll past 1st section's delegate (10px height)
 +    QTRY_COMPARE(listview->contentY(), expectedPos);
 +
 +    expectedPos += 20 + 10;     // scroll past 1st section and section delegate of 2nd section
 +    QTest::keyClick(canvas, Qt::Key_Down);
 +
 +    QTRY_COMPARE(listview->contentY(), expectedPos);
 +
 +    expectedPos += 20;     // scroll past 1st item of 2nd section
 +    QTest::keyClick(canvas, Qt::Key_Down);
 +    QTRY_COMPARE(listview->contentY(), expectedPos);
 +
 +    expectedPos += 20 + 10;     // scroll past 2nd item of 2nd section and section delegate of 3rd section
 +    QTest::keyClick(canvas, Qt::Key_Down);
 +    QTRY_COMPARE(listview->contentY(), expectedPos);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::spacing()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_VERIFY(item->y() == i*20);
 +    }
 +
 +    listview->setSpacing(10);
 +    QTRY_VERIFY(listview->spacing() == 10);
 +
 +    // Confirm items positioned correctly
 +    QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() == 11);
 +    for (int i = 0; i < 11; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_VERIFY(item->y() == i*30);
 +    }
 +
 +    listview->setSpacing(0);
 +
 +    // Confirm items positioned correctly
 +    QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() >= 16);
 +    for (int i = 0; i < 16; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.0);
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +template <typename T>
 +void tst_QQuickListView::sections(const QUrl &source)
 +{
 +    QQuickView *canvas = createView();
 +
 +    T model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), QString::number(i/5));
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(source);
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), qreal(i*20 + ((i+4)/5) * 20));
 +        QQuickText *next = findItem<QQuickText>(item, "nextSection");
 +        QCOMPARE(next->text().toInt(), (i+1)/5);
 +    }
 +
 +    QSignalSpy currentSectionChangedSpy(listview, SIGNAL(currentSectionChanged()));
 +
 +    // Remove section boundary
 +    model.removeItem(5);
 +    QTRY_COMPARE(listview->count(), model.count());
 +
 +    // New section header created
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 5);
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->height(), 40.0);
 +
 +    model.insertItem(3, "New Item", "0");
 +    QTRY_COMPARE(listview->count(), model.count());
 +
 +    // Section header moved
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 5);
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->height(), 20.0);
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 6);
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->height(), 40.0);
 +
 +    // insert item which will become a section header
 +    model.insertItem(6, "Replace header", "1");
 +    QTRY_COMPARE(listview->count(), model.count());
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 6);
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->height(), 40.0);
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 7);
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->height(), 20.0);
 +
 +    QTRY_COMPARE(listview->currentSection(), QString("0"));
 +
 +    listview->setContentY(140);
 +    QTRY_COMPARE(listview->currentSection(), QString("1"));
 +
 +    QTRY_COMPARE(currentSectionChangedSpy.count(), 1);
 +
 +    listview->setContentY(20);
 +    QTRY_COMPARE(listview->currentSection(), QString("0"));
 +
 +    QTRY_COMPARE(currentSectionChangedSpy.count(), 2);
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 1);
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->height(), 20.0);
 +
 +    // check that headers change when item changes
 +    listview->setContentY(0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    model.modifyItem(0, "changed", "2");
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 1);
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->height(), 40.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::sectionsDelegate()
 +{
 +    QSKIP("QTBUG-24395");
 +
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), QString::number(i/5));
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("listview-sections_delegate.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), qreal(i*20 + ((i+5)/5) * 20));
 +        QQuickText *next = findItem<QQuickText>(item, "nextSection");
 +        QCOMPARE(next->text().toInt(), (i+1)/5);
 +    }
 +
 +    for (int i = 0; i < 3; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "sect_" + QString::number(i));
 +        QVERIFY(item);
 +        QTRY_COMPARE(item->y(), qreal(i*20*6));
 +    }
 +
 +    // ensure section header is maintained in view
 +    listview->setCurrentIndex(20);
 +    QTRY_VERIFY(listview->contentY() >= 200.0);
 +    listview->setCurrentIndex(0);
 +    QTRY_COMPARE(listview->contentY(), 0.0);
 +
 +    // change section
 +    model.modifyItem(0, "One", "aaa");
 +    model.modifyItem(1, "Two", "aaa");
 +    model.modifyItem(2, "Three", "aaa");
 +    model.modifyItem(3, "Four", "aaa");
 +    model.modifyItem(4, "Five", "aaa");
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    for (int i = 0; i < 3; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem,
 +                "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
 +        QVERIFY(item);
 +        QTRY_COMPARE(item->y(), qreal(i*20*6));
 +    }
 +
 +    // remove section boundary
 +    model.removeItem(5);
 +    QTRY_COMPARE(listview->count(), model.count());
 +    for (int i = 0; i < 3; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem,
 +                "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
 +        QVERIFY(item);
 +    }
 +
 +    // QTBUG-17606
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "sect_1");
 +    QCOMPARE(items.count(), 1);
 +
 +    // QTBUG-17759
 +    model.modifyItem(0, "One", "aaa");
 +    model.modifyItem(1, "One", "aaa");
 +    model.modifyItem(2, "One", "aaa");
 +    model.modifyItem(3, "Four", "aaa");
 +    model.modifyItem(4, "Four", "aaa");
 +    model.modifyItem(5, "Four", "aaa");
 +    model.modifyItem(6, "Five", "aaa");
 +    model.modifyItem(7, "Five", "aaa");
 +    model.modifyItem(8, "Five", "aaa");
 +    model.modifyItem(9, "Two", "aaa");
 +    model.modifyItem(10, "Two", "aaa");
 +    model.modifyItem(11, "Two", "aaa");
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "sect_aaa").count(), 1);
 +    canvas->rootObject()->setProperty("sectionProperty", "name");
 +    // ensure view has settled.
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "sect_Four").count(), 1);
 +    for (int i = 0; i < 4; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem,
 +                "sect_" + model.name(i*3));
 +        QVERIFY(item);
 +        QTRY_COMPARE(item->y(), qreal(i*20*4));
 +    }
 +
 +    // QTBUG-17769
 +    model.removeItems(10, 20);
 +    // ensure view has settled.
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper").count(), 10);
 +    // Drag view up beyond bounds
 +    QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(20,20));
 +    {
 +        QMouseEvent mv(QEvent::MouseMove, QPoint(20,0), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
 +        QGuiApplication::sendEvent(canvas, &mv);
 +    }
 +    {
 +        QMouseEvent mv(QEvent::MouseMove, QPoint(20,-50), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
 +        QGuiApplication::sendEvent(canvas, &mv);
 +    }
 +    {
 +        QMouseEvent mv(QEvent::MouseMove, QPoint(20,-200), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
 +        QGuiApplication::sendEvent(canvas, &mv);
 +    }
 +    QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(20,-200));
 +    // view should settle back at 0
 +    QTRY_COMPARE(listview->contentY(), 0.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::sectionsPositioning()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), QString::number(i/5));
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("listview-sections_delegate.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +    canvas->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels | QQuickViewSection::CurrentLabelAtStart | QQuickViewSection::NextLabelAtEnd)));
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    for (int i = 0; i < 3; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "sect_" + QString::number(i));
 +        QVERIFY(item);
 +        QTRY_COMPARE(item->y(), qreal(i*20*6));
 +    }
 +
 +    QQuickItem *topItem = findVisibleChild(contentItem, "sect_0"); // section header
 +    QVERIFY(topItem);
 +    QCOMPARE(topItem->y(), 0.);
 +
 +    QQuickItem *bottomItem = findVisibleChild(contentItem, "sect_3"); // section footer
 +    QVERIFY(bottomItem);
 +    QCOMPARE(bottomItem->y(), 300.);
 +
 +    // move down a little and check that section header is at top
 +    listview->setContentY(10);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    QCOMPARE(topItem->y(), 0.);
 +
 +    // push the top header up
 +    listview->setContentY(110);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    topItem = findVisibleChild(contentItem, "sect_0"); // section header
 +    QVERIFY(topItem);
 +    QCOMPARE(topItem->y(), 100.);
 +
 +    QQuickItem *item = findVisibleChild(contentItem, "sect_1");
 +    QVERIFY(item);
 +    QCOMPARE(item->y(), 120.);
 +
 +    bottomItem = findVisibleChild(contentItem, "sect_4"); // section footer
 +    QVERIFY(bottomItem);
 +    QCOMPARE(bottomItem->y(), 410.);
 +
 +    // Move past section 0
 +    listview->setContentY(120);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    topItem = findVisibleChild(contentItem, "sect_0"); // section header
 +    QVERIFY(!topItem);
 +
 +    // Push section footer down
 +    listview->setContentY(70);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    bottomItem = findVisibleChild(contentItem, "sect_4"); // section footer
 +    QVERIFY(bottomItem);
 +    QCOMPARE(bottomItem->y(), 380.);
 +
 +    // Change current section
 +    listview->setContentY(10);
 +    model.modifyItem(0, "One", "aaa");
 +    model.modifyItem(1, "Two", "aaa");
 +    model.modifyItem(2, "Three", "aaa");
 +    model.modifyItem(3, "Four", "aaa");
 +    model.modifyItem(4, "Five", "aaa");
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QTRY_COMPARE(listview->currentSection(), QString("aaa"));
 +
 +    for (int i = 0; i < 3; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem,
 +                "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
 +        QVERIFY(item);
 +        QTRY_COMPARE(item->y(), qreal(i*20*6));
 +    }
 +
 +    QTRY_VERIFY(topItem = findVisibleChild(contentItem, "sect_aaa")); // section header
 +    QCOMPARE(topItem->y(), 10.);
 +
 +    // remove section boundary
 +    listview->setContentY(120);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    model.removeItem(5);
 +    QTRY_COMPARE(listview->count(), model.count());
-     // add transitions on the left, moves on the right
++    for (int i = 1; i < 3; ++i) {
++        QQuickItem *item = findVisibleChild(contentItem,
++                "sect_" + QString::number(i));
 +        QVERIFY(item);
 +        QTRY_COMPARE(item->y(), qreal(i*20*6));
 +    }
 +
 +    QVERIFY(topItem = findVisibleChild(contentItem, "sect_1"));
 +    QTRY_COMPARE(topItem->y(), 120.);
 +
 +    // Change the next section
 +    listview->setContentY(0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    bottomItem = findVisibleChild(contentItem, "sect_3"); // section footer
 +    QVERIFY(bottomItem);
 +    QTRY_COMPARE(bottomItem->y(), 300.);
 +
 +    model.modifyItem(14, "New", "new");
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QTRY_VERIFY(bottomItem = findVisibleChild(contentItem, "sect_new")); // section footer
 +    QTRY_COMPARE(bottomItem->y(), 300.);
 +
 +    // Turn sticky footer off
 +    listview->setContentY(20);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    canvas->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels | QQuickViewSection::CurrentLabelAtStart)));
 +    QTRY_VERIFY(item = findVisibleChild(contentItem, "sect_new")); // inline label restored
 +    QCOMPARE(item->y(), 340.);
 +
 +    // Turn sticky header off
 +    listview->setContentY(30);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    canvas->rootObject()->setProperty("sectionPositioning", QVariant(int(QQuickViewSection::InlineLabels)));
 +    QTRY_VERIFY(item = findVisibleChild(contentItem, "sect_aaa")); // inline label restored
 +    QCOMPARE(item->y(), 0.);
 +
 +    delete canvas;
 +}
 +
++void tst_QQuickListView::sectionPropertyChange()
++{
++    QQuickView *canvas = createView();
++
++    canvas->setSource(testFileUrl("sectionpropertychange.qml"));
++    canvas->show();
++    qApp->processEvents();
++
++    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
++    QTRY_VERIFY(listview != 0);
++
++    QQuickItem *contentItem = listview->contentItem();
++    QTRY_VERIFY(contentItem != 0);
++
++    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
++
++    // Confirm items positioned correctly
++    for (int i = 0; i < 2; ++i) {
++        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
++        QTRY_VERIFY(item);
++        QTRY_COMPARE(item->y(), qreal(25. + i*75.));
++    }
++
++    QMetaObject::invokeMethod(canvas->rootObject(), "switchGroups");
++    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
++
++    // Confirm items positioned correctly
++    for (int i = 0; i < 2; ++i) {
++        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
++        QTRY_VERIFY(item);
++        QTRY_COMPARE(item->y(), qreal(25. + i*75.));
++    }
++
++    QMetaObject::invokeMethod(canvas->rootObject(), "switchGroups");
++    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
++
++    // Confirm items positioned correctly
++    for (int i = 0; i < 2; ++i) {
++        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
++        QTRY_VERIFY(item);
++        QTRY_COMPARE(item->y(), qreal(25. + i*75.));
++    }
++
++    delete canvas;
++}
++
 +void tst_QQuickListView::currentIndex_delayedItemCreation()
 +{
 +    QFETCH(bool, setCurrentToZero);
 +
 +    QQuickView *canvas = createView();
 +
 +    // test currentIndexChanged() is emitted even if currentIndex = 0 on start up
 +    // (since the currentItem will have changed and that shares the same index)
 +    canvas->rootContext()->setContextProperty("setCurrentToZero", setCurrentToZero);
 +
 +    canvas->setSource(testFileUrl("fillModelOnComponentCompleted.qml"));
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QSignalSpy spy(listview, SIGNAL(currentItemChanged()));
 +    QCOMPARE(listview->currentIndex(), 0);
 +    QTRY_COMPARE(spy.count(), 1);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::currentIndex_delayedItemCreation_data()
 +{
 +    QTest::addColumn<bool>("setCurrentToZero");
 +
 +    QTest::newRow("set to 0") << true;
 +    QTest::newRow("don't set to 0") << false;
 +}
 +
 +void tst_QQuickListView::currentIndex()
 +{
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), QString::number(i));
 +
 +    QQuickView *canvas = new QQuickView(0);
 +    canvas->setGeometry(0,0,240,320);
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testWrap", QVariant(false));
 +
 +    QString filename(testFile("listview-initCurrent.qml"));
 +    canvas->setSource(QUrl::fromLocalFile(filename));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // current item should be 20th item at startup
 +    // and current item should be in view
 +    QCOMPARE(listview->currentIndex(), 20);
 +    QCOMPARE(listview->contentY(), 100.0);
 +    QCOMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 20));
 +    QCOMPARE(listview->highlightItem()->y(), listview->currentItem()->y());
 +
 +    // no wrap
 +    listview->setCurrentIndex(0);
 +    QCOMPARE(listview->currentIndex(), 0);
 +    // confirm that the velocity is updated
 +    QTRY_VERIFY(listview->verticalVelocity() != 0.0);
 +
 +    listview->incrementCurrentIndex();
 +    QCOMPARE(listview->currentIndex(), 1);
 +    listview->decrementCurrentIndex();
 +    QCOMPARE(listview->currentIndex(), 0);
 +
 +    listview->decrementCurrentIndex();
 +    QCOMPARE(listview->currentIndex(), 0);
 +
 +    // with wrap
 +    ctxt->setContextProperty("testWrap", QVariant(true));
 +    QVERIFY(listview->isWrapEnabled());
 +
 +    listview->decrementCurrentIndex();
 +    QCOMPARE(listview->currentIndex(), model.count()-1);
 +
 +    QTRY_COMPARE(listview->contentY(), 280.0);
 +
 +    listview->incrementCurrentIndex();
 +    QCOMPARE(listview->currentIndex(), 0);
 +
 +    QTRY_COMPARE(listview->contentY(), 0.0);
 +
 +
 +    // footer should become visible if it is out of view, and then current index is set to count-1
 +    canvas->rootObject()->setProperty("showFooter", true);
 +    QTRY_VERIFY(listview->footerItem());
 +    listview->setCurrentIndex(model.count()-2);
 +    QTRY_VERIFY(listview->footerItem()->y() > listview->contentY() + listview->height());
 +    listview->setCurrentIndex(model.count()-1);
 +    QTRY_COMPARE(listview->contentY() + listview->height(), (20.0 * model.count()) + listview->footerItem()->height());
 +    canvas->rootObject()->setProperty("showFooter", false);
 +
 +    // header should become visible if it is out of view, and then current index is set to 0
 +    canvas->rootObject()->setProperty("showHeader", true);
 +    QTRY_VERIFY(listview->headerItem());
 +    listview->setCurrentIndex(1);
 +    QTRY_VERIFY(listview->headerItem()->y() + listview->headerItem()->height() < listview->contentY());
 +    listview->setCurrentIndex(0);
 +    QTRY_COMPARE(listview->contentY(), -listview->headerItem()->height());
 +    canvas->rootObject()->setProperty("showHeader", false);
 +
 +
 +    // Test keys
 +    canvas->show();
 +    canvas->requestActivateWindow();
 +    QTest::qWaitForWindowShown(canvas);
 +    QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
 +
 +    listview->setCurrentIndex(0);
 +
 +    QTest::keyClick(canvas, Qt::Key_Down);
 +    QCOMPARE(listview->currentIndex(), 1);
 +
 +    QTest::keyClick(canvas, Qt::Key_Up);
 +    QCOMPARE(listview->currentIndex(), 0);
 +
 +    // hold down Key_Down
 +    for (int i=0; i<model.count()-1; i++) {
 +        QTest::simulateEvent(canvas, true, Qt::Key_Down, Qt::NoModifier, "", true);
 +        QTRY_COMPARE(listview->currentIndex(), i+1);
 +    }
 +    QTest::keyRelease(canvas, Qt::Key_Down);
 +    QTRY_COMPARE(listview->currentIndex(), model.count()-1);
 +    QTRY_COMPARE(listview->contentY(), 280.0);
 +
 +    // hold down Key_Up
 +    for (int i=model.count()-1; i > 0; i--) {
 +        QTest::simulateEvent(canvas, true, Qt::Key_Up, Qt::NoModifier, "", true);
 +        QTRY_COMPARE(listview->currentIndex(), i-1);
 +    }
 +    QTest::keyRelease(canvas, Qt::Key_Up);
 +    QTRY_COMPARE(listview->currentIndex(), 0);
 +    QTRY_COMPARE(listview->contentY(), 0.0);
 +
 +
 +    // turn off auto highlight
 +    listview->setHighlightFollowsCurrentItem(false);
 +    QVERIFY(listview->highlightFollowsCurrentItem() == false);
 +
 +    QVERIFY(listview->highlightItem());
 +    qreal hlPos = listview->highlightItem()->y();
 +
 +    listview->setCurrentIndex(4);
 +    QTRY_COMPARE(listview->highlightItem()->y(), hlPos);
 +
 +    // insert item before currentIndex
 +    listview->setCurrentIndex(28);
 +    model.insertItem(0, "Foo", "1111");
 +    QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
 +
 +    // check removing highlight by setting currentIndex to -1;
 +    listview->setCurrentIndex(-1);
 +
 +    QCOMPARE(listview->currentIndex(), -1);
 +    QVERIFY(!listview->highlightItem());
 +    QVERIFY(!listview->currentItem());
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::noCurrentIndex()
 +{
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), QString::number(i));
 +
 +    QQuickView *canvas = new QQuickView(0);
 +    canvas->setGeometry(0,0,240,320);
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    QString filename(testFile("listview-noCurrent.qml"));
 +    canvas->setSource(QUrl::fromLocalFile(filename));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // current index should be -1 at startup
 +    // and we should not have a currentItem or highlightItem
 +    QCOMPARE(listview->currentIndex(), -1);
 +    QCOMPARE(listview->contentY(), 0.0);
 +    QVERIFY(!listview->highlightItem());
 +    QVERIFY(!listview->currentItem());
 +
 +    listview->setCurrentIndex(2);
 +    QCOMPARE(listview->currentIndex(), 2);
 +    QVERIFY(listview->highlightItem());
 +    QVERIFY(listview->currentItem());
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::itemList()
 +{
 +    QQuickView *canvas = createView();
 +    canvas->setSource(testFileUrl("itemlist.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "view");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QQuickVisualItemModel *model = canvas->rootObject()->findChild<QQuickVisualItemModel*>("itemModel");
 +    QTRY_VERIFY(model != 0);
 +
 +    QTRY_VERIFY(model->count() == 3);
 +    QTRY_COMPARE(listview->currentIndex(), 0);
 +
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "item1");
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->x(), 0.0);
 +    QCOMPARE(item->height(), listview->height());
 +
 +    QQuickText *text = findItem<QQuickText>(contentItem, "text1");
 +    QTRY_VERIFY(text);
 +    QTRY_COMPARE(text->text(), QLatin1String("index: 0"));
 +
 +    listview->setCurrentIndex(2);
 +
 +    item = findItem<QQuickItem>(contentItem, "item3");
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->x(), 480.0);
 +
 +    text = findItem<QQuickText>(contentItem, "text3");
 +    QTRY_VERIFY(text);
 +    QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::cacheBuffer()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 90; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_VERIFY(listview->delegate() != 0);
 +    QTRY_VERIFY(listview->model() != 0);
 +    QTRY_VERIFY(listview->highlight() != 0);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_VERIFY(item->y() == i*20);
 +    }
 +
 +    QQmlIncubationController controller;
 +    canvas->engine()->setIncubationController(&controller);
 +
 +    testObject->setCacheBuffer(200);
 +    QTRY_VERIFY(listview->cacheBuffer() == 200);
 +
 +    // items will be created one at a time
 +    for (int i = itemCount; i < qMin(itemCount+10,model.count()); ++i) {
 +        QVERIFY(findItem<QQuickItem>(listview, "wrapper", i) == 0);
 +        QQuickItem *item = 0;
 +        while (!item) {
 +            bool b = false;
 +            controller.incubateWhile(&b);
 +            item = findItem<QQuickItem>(listview, "wrapper", i);
 +        }
 +    }
 +
 +    {
 +        bool b = true;
 +        controller.incubateWhile(&b);
 +    }
 +
 +    int newItemCount = 0;
 +    newItemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +
 +    // Confirm items positioned correctly
 +    for (int i = 0; i < model.count() && i < newItemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_VERIFY(item->y() == i*20);
 +    }
 +
 +    // move view and confirm items in view are visible immediately and outside are created async
 +    listview->setContentY(300);
 +
 +    for (int i = 15; i < 32; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QVERIFY(item);
 +        QVERIFY(item->y() == i*20);
 +    }
 +
 +    QVERIFY(findItem<QQuickItem>(listview, "wrapper", 32) == 0);
 +
 +    // ensure buffered items are created
 +    for (int i = 32; i < qMin(41,model.count()); ++i) {
 +        QQuickItem *item = 0;
 +        while (!item) {
 +            qGuiApp->processEvents(); // allow refill to happen
 +            bool b = false;
 +            controller.incubateWhile(&b);
 +            item = findItem<QQuickItem>(listview, "wrapper", i);
 +        }
 +    }
 +
 +    {
 +        bool b = true;
 +        controller.incubateWhile(&b);
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::positionViewAtIndex()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 40; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +    canvas->show();
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.);
 +    }
 +
 +    // Position on a currently visible item
 +    listview->positionViewAtIndex(3, QQuickListView::Beginning);
 +    QTRY_COMPARE(listview->contentY(), 60.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.);
 +    }
 +
 +    // Position on an item beyond the visible items
 +    listview->positionViewAtIndex(22, QQuickListView::Beginning);
 +    QTRY_COMPARE(listview->contentY(), 440.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.);
 +    }
 +
 +    // Position on an item that would leave empty space if positioned at the top
 +    listview->positionViewAtIndex(28, QQuickListView::Beginning);
 +    QTRY_COMPARE(listview->contentY(), 480.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.);
 +    }
 +
 +    // Position at the beginning again
 +    listview->positionViewAtIndex(0, QQuickListView::Beginning);
 +    QTRY_COMPARE(listview->contentY(), 0.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.);
 +    }
 +
 +    // Position at End using last index
 +    listview->positionViewAtIndex(model.count()-1, QQuickListView::End);
 +    QTRY_COMPARE(listview->contentY(), 480.);
 +
 +    // Confirm items positioned correctly
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 24; i < model.count(); ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.);
 +    }
 +
 +    // Position at End
 +    listview->positionViewAtIndex(20, QQuickListView::End);
 +    QTRY_COMPARE(listview->contentY(), 100.);
 +
 +    // Position in Center
 +    listview->positionViewAtIndex(15, QQuickListView::Center);
 +    QTRY_COMPARE(listview->contentY(), 150.);
 +
 +    // Ensure at least partially visible
 +    listview->positionViewAtIndex(15, QQuickListView::Visible);
 +    QTRY_COMPARE(listview->contentY(), 150.);
 +
 +    listview->setContentY(302);
 +    listview->positionViewAtIndex(15, QQuickListView::Visible);
 +    QTRY_COMPARE(listview->contentY(), 302.);
 +
 +    listview->setContentY(320);
 +    listview->positionViewAtIndex(15, QQuickListView::Visible);
 +    QTRY_COMPARE(listview->contentY(), 300.);
 +
 +    listview->setContentY(85);
 +    listview->positionViewAtIndex(20, QQuickListView::Visible);
 +    QTRY_COMPARE(listview->contentY(), 85.);
 +
 +    listview->setContentY(75);
 +    listview->positionViewAtIndex(20, QQuickListView::Visible);
 +    QTRY_COMPARE(listview->contentY(), 100.);
 +
 +    // Ensure completely visible
 +    listview->setContentY(120);
 +    listview->positionViewAtIndex(20, QQuickListView::Contain);
 +    QTRY_COMPARE(listview->contentY(), 120.);
 +
 +    listview->setContentY(302);
 +    listview->positionViewAtIndex(15, QQuickListView::Contain);
 +    QTRY_COMPARE(listview->contentY(), 300.);
 +
 +    listview->setContentY(85);
 +    listview->positionViewAtIndex(20, QQuickListView::Contain);
 +    QTRY_COMPARE(listview->contentY(), 100.);
 +
 +    // positionAtBeginnging
 +    listview->positionViewAtBeginning();
 +    QTRY_COMPARE(listview->contentY(), 0.);
 +
 +    listview->setContentY(80);
 +    canvas->rootObject()->setProperty("showHeader", true);
 +    listview->positionViewAtBeginning();
 +    QTRY_COMPARE(listview->contentY(), -30.);
 +
 +    // positionAtEnd
 +    listview->positionViewAtEnd();
 +    QTRY_COMPARE(listview->contentY(), 480.); // 40*20 - 320
 +
 +    listview->setContentY(80);
 +    canvas->rootObject()->setProperty("showFooter", true);
 +    listview->positionViewAtEnd();
 +    QTRY_COMPARE(listview->contentY(), 510.);
 +
 +    // set current item to outside visible view, position at beginning
 +    // and ensure highlight moves to current item
 +    listview->setCurrentIndex(1);
 +    listview->positionViewAtBeginning();
 +    QTRY_COMPARE(listview->contentY(), -30.);
 +    QVERIFY(listview->highlightItem());
 +    QCOMPARE(listview->highlightItem()->y(), 20.);
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::resetModel()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QStringList strings;
 +    strings << "one" << "two" << "three";
 +    QStringListModel model(strings);
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("displaylist.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QTRY_COMPARE(listview->count(), model.rowCount());
 +
 +    for (int i = 0; i < model.rowCount(); ++i) {
 +        QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
 +        QTRY_VERIFY(display != 0);
 +        QTRY_COMPARE(display->text(), strings.at(i));
 +    }
 +
 +    strings.clear();
 +    strings << "four" << "five" << "six" << "seven";
 +    model.setStringList(strings);
 +
 +    QTRY_COMPARE(listview->count(), model.rowCount());
 +
 +    for (int i = 0; i < model.rowCount(); ++i) {
 +        QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
 +        QTRY_VERIFY(display != 0);
 +        QTRY_COMPARE(display->text(), strings.at(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::propertyChanges()
 +{
 +    QQuickView *canvas = createView();
 +    QTRY_VERIFY(canvas);
 +    canvas->setSource(testFileUrl("propertychangestest.qml"));
 +
 +    QQuickListView *listView = canvas->rootObject()->findChild<QQuickListView*>("listView");
 +    QTRY_VERIFY(listView);
 +
 +    QSignalSpy highlightFollowsCurrentItemSpy(listView, SIGNAL(highlightFollowsCurrentItemChanged()));
 +    QSignalSpy preferredHighlightBeginSpy(listView, SIGNAL(preferredHighlightBeginChanged()));
 +    QSignalSpy preferredHighlightEndSpy(listView, SIGNAL(preferredHighlightEndChanged()));
 +    QSignalSpy highlightRangeModeSpy(listView, SIGNAL(highlightRangeModeChanged()));
 +    QSignalSpy keyNavigationWrapsSpy(listView, SIGNAL(keyNavigationWrapsChanged()));
 +    QSignalSpy cacheBufferSpy(listView, SIGNAL(cacheBufferChanged()));
 +    QSignalSpy snapModeSpy(listView, SIGNAL(snapModeChanged()));
 +
 +    QTRY_COMPARE(listView->highlightFollowsCurrentItem(), true);
 +    QTRY_COMPARE(listView->preferredHighlightBegin(), 0.0);
 +    QTRY_COMPARE(listView->preferredHighlightEnd(), 0.0);
 +    QTRY_COMPARE(listView->highlightRangeMode(), QQuickListView::ApplyRange);
 +    QTRY_COMPARE(listView->isWrapEnabled(), true);
 +    QTRY_COMPARE(listView->cacheBuffer(), 10);
 +    QTRY_COMPARE(listView->snapMode(), QQuickListView::SnapToItem);
 +
 +    listView->setHighlightFollowsCurrentItem(false);
 +    listView->setPreferredHighlightBegin(1.0);
 +    listView->setPreferredHighlightEnd(1.0);
 +    listView->setHighlightRangeMode(QQuickListView::StrictlyEnforceRange);
 +    listView->setWrapEnabled(false);
 +    listView->setCacheBuffer(3);
 +    listView->setSnapMode(QQuickListView::SnapOneItem);
 +
 +    QTRY_COMPARE(listView->highlightFollowsCurrentItem(), false);
 +    QTRY_COMPARE(listView->preferredHighlightBegin(), 1.0);
 +    QTRY_COMPARE(listView->preferredHighlightEnd(), 1.0);
 +    QTRY_COMPARE(listView->highlightRangeMode(), QQuickListView::StrictlyEnforceRange);
 +    QTRY_COMPARE(listView->isWrapEnabled(), false);
 +    QTRY_COMPARE(listView->cacheBuffer(), 3);
 +    QTRY_COMPARE(listView->snapMode(), QQuickListView::SnapOneItem);
 +
 +    QTRY_COMPARE(highlightFollowsCurrentItemSpy.count(),1);
 +    QTRY_COMPARE(preferredHighlightBeginSpy.count(),1);
 +    QTRY_COMPARE(preferredHighlightEndSpy.count(),1);
 +    QTRY_COMPARE(highlightRangeModeSpy.count(),1);
 +    QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
 +    QTRY_COMPARE(cacheBufferSpy.count(),1);
 +    QTRY_COMPARE(snapModeSpy.count(),1);
 +
 +    listView->setHighlightFollowsCurrentItem(false);
 +    listView->setPreferredHighlightBegin(1.0);
 +    listView->setPreferredHighlightEnd(1.0);
 +    listView->setHighlightRangeMode(QQuickListView::StrictlyEnforceRange);
 +    listView->setWrapEnabled(false);
 +    listView->setCacheBuffer(3);
 +    listView->setSnapMode(QQuickListView::SnapOneItem);
 +
 +    QTRY_COMPARE(highlightFollowsCurrentItemSpy.count(),1);
 +    QTRY_COMPARE(preferredHighlightBeginSpy.count(),1);
 +    QTRY_COMPARE(preferredHighlightEndSpy.count(),1);
 +    QTRY_COMPARE(highlightRangeModeSpy.count(),1);
 +    QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
 +    QTRY_COMPARE(cacheBufferSpy.count(),1);
 +    QTRY_COMPARE(snapModeSpy.count(),1);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::componentChanges()
 +{
 +    QQuickView *canvas = createView();
 +    QTRY_VERIFY(canvas);
 +    canvas->setSource(testFileUrl("propertychangestest.qml"));
 +
 +    QQuickListView *listView = canvas->rootObject()->findChild<QQuickListView*>("listView");
 +    QTRY_VERIFY(listView);
 +
 +    QQmlComponent component(canvas->engine());
 +    component.setData("import QtQuick 2.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
 +
 +    QQmlComponent delegateComponent(canvas->engine());
 +    delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
 +
 +    QSignalSpy highlightSpy(listView, SIGNAL(highlightChanged()));
 +    QSignalSpy delegateSpy(listView, SIGNAL(delegateChanged()));
 +    QSignalSpy headerSpy(listView, SIGNAL(headerChanged()));
 +    QSignalSpy footerSpy(listView, SIGNAL(footerChanged()));
 +
 +    listView->setHighlight(&component);
 +    listView->setHeader(&component);
 +    listView->setFooter(&component);
 +    listView->setDelegate(&delegateComponent);
 +
 +    QTRY_COMPARE(listView->highlight(), &component);
 +    QTRY_COMPARE(listView->header(), &component);
 +    QTRY_COMPARE(listView->footer(), &component);
 +    QTRY_COMPARE(listView->delegate(), &delegateComponent);
 +
 +    QTRY_COMPARE(highlightSpy.count(),1);
 +    QTRY_COMPARE(delegateSpy.count(),1);
 +    QTRY_COMPARE(headerSpy.count(),1);
 +    QTRY_COMPARE(footerSpy.count(),1);
 +
 +    listView->setHighlight(&component);
 +    listView->setHeader(&component);
 +    listView->setFooter(&component);
 +    listView->setDelegate(&delegateComponent);
 +
 +    QTRY_COMPARE(highlightSpy.count(),1);
 +    QTRY_COMPARE(delegateSpy.count(),1);
 +    QTRY_COMPARE(headerSpy.count(),1);
 +    QTRY_COMPARE(footerSpy.count(),1);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::modelChanges()
 +{
 +    QQuickView *canvas = createView();
 +    QTRY_VERIFY(canvas);
 +    canvas->setSource(testFileUrl("propertychangestest.qml"));
 +
 +    QQuickListView *listView = canvas->rootObject()->findChild<QQuickListView*>("listView");
 +    QTRY_VERIFY(listView);
 +
 +    QQuickListModel *alternateModel = canvas->rootObject()->findChild<QQuickListModel*>("alternateModel");
 +    QTRY_VERIFY(alternateModel);
 +    QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
 +    QSignalSpy modelSpy(listView, SIGNAL(modelChanged()));
 +
 +    listView->setModel(modelVariant);
 +    QTRY_COMPARE(listView->model(), modelVariant);
 +    QTRY_COMPARE(modelSpy.count(),1);
 +
 +    listView->setModel(modelVariant);
 +    QTRY_COMPARE(modelSpy.count(),1);
 +
 +    listView->setModel(QVariant());
 +    QTRY_COMPARE(modelSpy.count(),2);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::QTBUG_9791()
 +{
 +    QQuickView *canvas = createView();
 +
 +    canvas->setSource(testFileUrl("strictlyenforcerange.qml"));
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_VERIFY(listview->delegate() != 0);
 +    QTRY_VERIFY(listview->model() != 0);
 +
 +    QMetaObject::invokeMethod(listview, "fillModel");
 +    qApp->processEvents();
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper", false).count();
 +    QCOMPARE(itemCount, 3);
 +
 +    for (int i = 0; i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->x(), i*300.0);
 +    }
 +
 +    // check that view is positioned correctly
 +    QTRY_COMPARE(listview->contentX(), 590.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::manualHighlight()
 +{
 +    QQuickView *canvas = new QQuickView(0);
 +    canvas->setGeometry(0,0,240,320);
 +
 +    QString filename(testFile("manual-highlight.qml"));
 +    canvas->setSource(QUrl::fromLocalFile(filename));
 +
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QTRY_COMPARE(listview->currentIndex(), 0);
 +    QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
 +    QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
 +
 +    listview->setCurrentIndex(2);
 +
 +    QTRY_COMPARE(listview->currentIndex(), 2);
 +    QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
 +    QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
 +
 +    // QTBUG-15972
 +    listview->positionViewAtIndex(3, QQuickListView::Contain);
 +
 +    QTRY_COMPARE(listview->currentIndex(), 2);
 +    QTRY_COMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
 +    QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::QTBUG_11105()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_VERIFY(item->y() == i*20);
 +    }
 +
 +    listview->positionViewAtIndex(20, QQuickListView::Beginning);
 +    QCOMPARE(listview->contentY(), 280.);
 +
 +    QmlListModel model2;
 +    for (int i = 0; i < 5; i++)
 +        model2.addItem("Item" + QString::number(i), "");
 +
 +    ctxt->setContextProperty("testModel", &model2);
 +
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    QCOMPARE(itemCount, 5);
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::header()
 +{
 +    QFETCH(QQuickListView::Orientation, orientation);
 +    QFETCH(Qt::LayoutDirection, layoutDirection);
 +    QFETCH(QPointF, initialHeaderPos);
 +    QFETCH(QPointF, firstDelegatePos);
 +    QFETCH(QPointF, initialContentPos);
 +    QFETCH(QPointF, changedHeaderPos);
 +    QFETCH(QPointF, changedContentPos);
 +    QFETCH(QPointF, resizeContentPos);
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQuickView *canvas = createView();
 +    canvas->rootContext()->setContextProperty("testModel", &model);
 +    canvas->rootContext()->setContextProperty("initialViewWidth", 240);
 +    canvas->rootContext()->setContextProperty("initialViewHeight", 320);
 +    canvas->setSource(testFileUrl("header.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    listview->setOrientation(orientation);
 +    listview->setLayoutDirection(layoutDirection);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QQuickText *header = 0;
 +    QTRY_VERIFY(header = findItem<QQuickText>(contentItem, "header"));
 +    QVERIFY(header == listview->headerItem());
 +
 +    QCOMPARE(header->width(), 100.);
 +    QCOMPARE(header->height(), 30.);
 +    QCOMPARE(header->pos(), initialHeaderPos);
 +    QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos);
 +
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item);
 +    QCOMPARE(item->pos(), firstDelegatePos);
 +
 +    model.clear();
 +    QTRY_COMPARE(listview->count(), model.count());
 +    QCOMPARE(header->pos(), initialHeaderPos); // header should stay where it is
 +
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QSignalSpy headerItemSpy(listview, SIGNAL(headerItemChanged()));
 +    QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
 +
 +    QCOMPARE(headerItemSpy.count(), 1);
 +
 +    header = findItem<QQuickText>(contentItem, "header");
 +    QVERIFY(!header);
 +    header = findItem<QQuickText>(contentItem, "header2");
 +    QVERIFY(header);
 +
 +    QVERIFY(header == listview->headerItem());
 +
 +    QCOMPARE(header->pos(), changedHeaderPos);
 +    QCOMPARE(header->width(), 50.);
 +    QCOMPARE(header->height(), 20.);
 +    QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), changedContentPos);
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item);
 +    QCOMPARE(item->pos(), firstDelegatePos);
 +
 +    delete canvas;
 +
 +
 +    // QTBUG-21207 header should become visible if view resizes from initial empty size
 +
 +    canvas = createView();
 +    canvas->rootContext()->setContextProperty("testModel", &model);
 +    canvas->rootContext()->setContextProperty("initialViewWidth", 0.0);
 +    canvas->rootContext()->setContextProperty("initialViewHeight", 0.0);
 +    canvas->setSource(testFileUrl("header.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    listview->setOrientation(orientation);
 +    listview->setLayoutDirection(layoutDirection);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    listview->setWidth(240);
 +    listview->setHeight(320);
 +    QTRY_COMPARE(listview->headerItem()->pos(), initialHeaderPos);
 +    QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos);
 +
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::header_data()
 +{
 +    QTest::addColumn<QQuickListView::Orientation>("orientation");
 +    QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
 +    QTest::addColumn<QPointF>("initialHeaderPos");
 +    QTest::addColumn<QPointF>("changedHeaderPos");
 +    QTest::addColumn<QPointF>("initialContentPos");
 +    QTest::addColumn<QPointF>("changedContentPos");
 +    QTest::addColumn<QPointF>("firstDelegatePos");
 +    QTest::addColumn<QPointF>("resizeContentPos");
 +
 +    // header1 = 100 x 30
 +    // header2 = 50 x 20
 +    // delegates = 240 x 20
 +    // view width = 240
 +
 +    // header above items, top left
 +    QTest::newRow("vertical, left to right") << QQuickListView::Vertical << Qt::LeftToRight
 +        << QPointF(0, -30)
 +        << QPointF(0, -20)
 +        << QPointF(0, -30)
 +        << QPointF(0, -20)
 +        << QPointF(0, 0)
 +        << QPointF(0, -10);
 +
 +    // header above items, top right
 +    QTest::newRow("vertical, layout right to left") << QQuickListView::Vertical << Qt::RightToLeft
 +        << QPointF(0, -30)
 +        << QPointF(0, -20)
 +        << QPointF(0, -30)
 +        << QPointF(0, -20)
 +        << QPointF(0, 0)
 +        << QPointF(0, -10);
 +
 +    // header to left of items
 +    QTest::newRow("horizontal, layout left to right") << QQuickListView::Horizontal << Qt::LeftToRight
 +        << QPointF(-100, 0)
 +        << QPointF(-50, 0)
 +        << QPointF(-100, 0)
 +        << QPointF(-50, 0)
 +        << QPointF(0, 0)
 +        << QPointF(-40, 0);
 +
 +    // header to right of items
 +    QTest::newRow("horizontal, layout right to left") << QQuickListView::Horizontal << Qt::RightToLeft
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(-240 + 100, 0)
 +        << QPointF(-240 + 50, 0)
 +        << QPointF(-240, 0)
 +        << QPointF(-240 + 40, 0);
 +}
 +
 +void tst_QQuickListView::header_delayItemCreation()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +
 +    canvas->rootContext()->setContextProperty("setCurrentToZero", QVariant(false));
 +    canvas->setSource(testFileUrl("fillModelOnComponentCompleted.qml"));
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QQuickText *header = findItem<QQuickText>(contentItem, "header");
 +    QVERIFY(header);
 +    QCOMPARE(header->y(), -header->height());
 +
 +    QCOMPARE(listview->contentY(), -header->height());
 +
 +    model.clear();
 +    QTRY_COMPARE(header->y(), -header->height());
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::footer()
 +{
 +    QFETCH(QQuickListView::Orientation, orientation);
 +    QFETCH(Qt::LayoutDirection, layoutDirection);
 +    QFETCH(QPointF, initialFooterPos);
 +    QFETCH(QPointF, firstDelegatePos);
 +    QFETCH(QPointF, initialContentPos);
 +    QFETCH(QPointF, changedFooterPos);
 +    QFETCH(QPointF, changedContentPos);
 +    QFETCH(QPointF, resizeContentPos);
 +
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 3; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("footer.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    listview->setOrientation(orientation);
 +    listview->setLayoutDirection(layoutDirection);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
 +    QVERIFY(footer);
 +
 +    QVERIFY(footer == listview->footerItem());
 +
 +    QCOMPARE(footer->pos(), initialFooterPos);
 +    QCOMPARE(footer->width(), 100.);
 +    QCOMPARE(footer->height(), 30.);
 +    QCOMPARE(QPointF(listview->contentX(), listview->contentY()), initialContentPos);
 +
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item);
 +    QCOMPARE(item->pos(), firstDelegatePos);
 +
 +    // remove one item
 +    model.removeItem(1);
 +
 +    if (orientation == QQuickListView::Vertical) {
 +        QTRY_COMPARE(footer->y(), initialFooterPos.y() - 20);   // delegate height = 20
 +    } else {
 +        QTRY_COMPARE(footer->x(), layoutDirection == Qt::LeftToRight ?
 +                initialFooterPos.x() - 40 : initialFooterPos.x() + 40);  // delegate width = 40
 +    }
 +
 +    // remove all items
 +    model.clear();
 +
 +    QPointF posWhenNoItems(0, 0);
 +    if (orientation == QQuickListView::Horizontal && layoutDirection == Qt::RightToLeft)
 +        posWhenNoItems.setX(-100);
 +    QTRY_COMPARE(footer->pos(), posWhenNoItems);
 +
 +    // if header is present, it's at a negative pos, so the footer should not move
 +    canvas->rootObject()->setProperty("showHeader", true);
 +    QTRY_COMPARE(footer->pos(), posWhenNoItems);
 +    canvas->rootObject()->setProperty("showHeader", false);
 +
 +    // add 30 items
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QSignalSpy footerItemSpy(listview, SIGNAL(footerItemChanged()));
 +    QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
 +
 +    QCOMPARE(footerItemSpy.count(), 1);
 +
 +    footer = findItem<QQuickText>(contentItem, "footer");
 +    QVERIFY(!footer);
 +    footer = findItem<QQuickText>(contentItem, "footer2");
 +    QVERIFY(footer);
 +
 +    QVERIFY(footer == listview->footerItem());
 +
 +    QCOMPARE(footer->pos(), changedFooterPos);
 +    QCOMPARE(footer->width(), 50.);
 +    QCOMPARE(footer->height(), 20.);
 +    QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), changedContentPos);
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    QVERIFY(item);
 +    QCOMPARE(item->pos(), firstDelegatePos);
 +
 +    listview->positionViewAtEnd();
 +    footer->setHeight(10);
 +    footer->setWidth(40);
 +    QTRY_COMPARE(QPointF(listview->contentX(), listview->contentY()), resizeContentPos);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::footer_data()
 +{
 +    QTest::addColumn<QQuickListView::Orientation>("orientation");
 +    QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
 +    QTest::addColumn<QPointF>("initialFooterPos");
 +    QTest::addColumn<QPointF>("changedFooterPos");
 +    QTest::addColumn<QPointF>("initialContentPos");
 +    QTest::addColumn<QPointF>("changedContentPos");
 +    QTest::addColumn<QPointF>("firstDelegatePos");
 +    QTest::addColumn<QPointF>("resizeContentPos");
 +
 +    // footer1 = 100 x 30
 +    // footer2 = 50 x 20
 +    // delegates = 40 x 20
 +    // view width = 240
 +    // view height = 320
 +
 +    // footer below items, bottom left
 +    QTest::newRow("vertical, layout left to right") << QQuickListView::Vertical << Qt::LeftToRight
 +        << QPointF(0, 3 * 20)
 +        << QPointF(0, 30 * 20)  // added 30 items
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(0, 30 * 20 - 320 + 10);
 +
 +    // footer below items, bottom right
 +    QTest::newRow("vertical, layout right to left") << QQuickListView::Vertical << Qt::RightToLeft
 +        << QPointF(0, 3 * 20)
 +        << QPointF(0, 30 * 20)
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(0, 30 * 20 - 320 + 10);
 +
 +    // footer to right of items
 +    QTest::newRow("horizontal, layout left to right") << QQuickListView::Horizontal << Qt::LeftToRight
 +        << QPointF(40 * 3, 0)
 +        << QPointF(40 * 30, 0)
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(0, 0)
 +        << QPointF(40 * 30 - 240 + 40, 0);
 +
 +    // footer to left of items
 +    QTest::newRow("horizontal, layout right to left") << QQuickListView::Horizontal << Qt::RightToLeft
 +        << QPointF(-(40 * 3) - 100, 0)
 +        << QPointF(-(40 * 30) - 50, 0)     // 50 = new footer width
 +        << QPointF(-240, 0)
 +        << QPointF(-240, 0)
 +        << QPointF(-40, 0)
 +        << QPointF(-(40 * 30) - 40, 0);
 +}
 +
 +class LVAccessor : public QQuickListView
 +{
 +public:
 +    qreal minY() const { return minYExtent(); }
 +    qreal maxY() const { return maxYExtent(); }
 +    qreal minX() const { return minXExtent(); }
 +    qreal maxX() const { return maxXExtent(); }
 +};
 +
 +void tst_QQuickListView::headerFooter()
 +{
 +    {
 +        // Vertical
 +        QQuickView *canvas = createView();
 +
 +        QmlListModel model;
 +        QQmlContext *ctxt = canvas->rootContext();
 +        ctxt->setContextProperty("testModel", &model);
 +
 +        canvas->setSource(testFileUrl("headerfooter.qml"));
 +        qApp->processEvents();
 +
 +        QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
 +        QTRY_VERIFY(listview != 0);
 +
 +        QQuickItem *contentItem = listview->contentItem();
 +        QTRY_VERIFY(contentItem != 0);
 +
 +        QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
 +        QVERIFY(header);
 +        QCOMPARE(header->y(), -header->height());
 +
 +        QQuickItem *footer = findItem<QQuickItem>(contentItem, "footer");
 +        QVERIFY(footer);
 +        QCOMPARE(footer->y(), 0.);
 +
 +        QCOMPARE(static_cast<LVAccessor*>(listview)->minY(), header->height());
 +        QCOMPARE(static_cast<LVAccessor*>(listview)->maxY(), header->height());
 +
 +        delete canvas;
 +    }
 +    {
 +        // Horizontal
 +        QQuickView *canvas = createView();
 +
 +        QmlListModel model;
 +        QQmlContext *ctxt = canvas->rootContext();
 +        ctxt->setContextProperty("testModel", &model);
 +
 +        canvas->setSource(testFileUrl("headerfooter.qml"));
 +        canvas->rootObject()->setProperty("horizontal", true);
 +        qApp->processEvents();
 +
 +        QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
 +        QTRY_VERIFY(listview != 0);
 +
 +        QQuickItem *contentItem = listview->contentItem();
 +        QTRY_VERIFY(contentItem != 0);
 +
 +        QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
 +        QVERIFY(header);
 +        QCOMPARE(header->x(), -header->width());
 +
 +        QQuickItem *footer = findItem<QQuickItem>(contentItem, "footer");
 +        QVERIFY(footer);
 +        QCOMPARE(footer->x(), 0.);
 +
 +        QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), header->width());
 +        QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), header->width());
 +
 +        delete canvas;
 +    }
 +    {
 +        // Horizontal RTL
 +        QQuickView *canvas = createView();
 +
 +        QmlListModel model;
 +        QQmlContext *ctxt = canvas->rootContext();
 +        ctxt->setContextProperty("testModel", &model);
 +
 +        canvas->setSource(testFileUrl("headerfooter.qml"));
 +        canvas->rootObject()->setProperty("horizontal", true);
 +        canvas->rootObject()->setProperty("rtl", true);
 +        qApp->processEvents();
 +
 +        QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
 +        QTRY_VERIFY(listview != 0);
 +
 +        QQuickItem *contentItem = listview->contentItem();
 +        QTRY_VERIFY(contentItem != 0);
 +
 +        QQuickItem *header = findItem<QQuickItem>(contentItem, "header");
 +        QVERIFY(header);
 +        QCOMPARE(header->x(), 0.);
 +
 +        QQuickItem *footer = findItem<QQuickItem>(contentItem, "footer");
 +        QVERIFY(footer);
 +        QCOMPARE(footer->x(), -footer->width());
 +
 +        QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), 240. - header->width());
 +        QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), 240. - header->width());
 +
 +        delete canvas;
 +    }
 +}
 +
 +void tst_QQuickListView::resizeView()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 40; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.);
 +    }
 +
 +    QVariant heightRatio;
 +    QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
 +    QCOMPARE(heightRatio.toReal(), 0.4);
 +
 +    listview->setHeight(200);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
 +    QCOMPARE(heightRatio.toReal(), 0.25);
 +
 +    // Ensure we handle -ve sizes
 +    listview->setHeight(-100);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper", false).count(), 1);
 +
 +    listview->setCacheBuffer(200);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper", false).count(), 11);
 +
 +    // ensure items in cache become visible
 +    listview->setHeight(200);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper", false).count(), 21);
 +
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper", false).count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.);
 +        QCOMPARE(item->isVisible(), i < 11); // inside view visible, outside not visible
 +    }
 +
 +    // ensure items outside view become invisible
 +    listview->setHeight(100);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper", false).count(), 16);
 +
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper", false).count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*20.);
 +        QCOMPARE(item->isVisible(), i < 6); // inside view visible, outside not visible
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::resizeViewAndRepaint()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 40; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("initialHeight", 100);
 +
 +    canvas->setSource(testFileUrl("resizeview.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // item at index 10 should not be currently visible
 +    QVERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
 +
 +    listview->setHeight(320);
 +
 +    QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", 10));
 +
 +    listview->setHeight(100);
 +    QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::sizeLessThan1()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("sizelessthan1.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // Confirm items positioned correctly
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i = 0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        if (!item) qWarning() << "Item" << i << "not found";
 +        QTRY_VERIFY(item);
 +        QTRY_COMPARE(item->y(), i*0.5);
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::QTBUG_14821()
 +{
 +    QQuickView *canvas = createView();
 +
 +    canvas->setSource(testFileUrl("qtbug14821.qml"));
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = qobject_cast<QQuickListView*>(canvas->rootObject());
 +    QVERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QVERIFY(contentItem != 0);
 +
 +    listview->decrementCurrentIndex();
 +    QCOMPARE(listview->currentIndex(), 99);
 +
 +    listview->incrementCurrentIndex();
 +    QCOMPARE(listview->currentIndex(), 0);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::resizeDelegate()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QStringList strings;
 +    for (int i = 0; i < 30; ++i)
 +        strings << QString::number(i);
 +    QStringListModel model(strings);
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("displaylist.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QVERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QCOMPARE(listview->count(), model.rowCount());
 +
 +    listview->setCurrentIndex(25);
 +    listview->setContentY(0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    for (int i = 0; i < 16; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY(item != 0);
 +        QCOMPARE(item->y(), i*20.0);
 +    }
 +
 +    QCOMPARE(listview->currentItem()->y(), 500.0);
 +    QTRY_COMPARE(listview->highlightItem()->y(), 500.0);
 +
 +    canvas->rootObject()->setProperty("delegateHeight", 30);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    for (int i = 0; i < 11; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY(item != 0);
 +        QTRY_COMPARE(item->y(), i*30.0);
 +    }
 +
 +    QTRY_COMPARE(listview->currentItem()->y(), 750.0);
 +    QTRY_COMPARE(listview->highlightItem()->y(), 750.0);
 +
 +    listview->setCurrentIndex(1);
 +    listview->positionViewAtIndex(25, QQuickListView::Beginning);
 +    listview->positionViewAtIndex(5, QQuickListView::Beginning);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    for (int i = 5; i < 16; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY(item != 0);
 +        QCOMPARE(item->y(), i*30.0);
 +    }
 +
 +    QTRY_COMPARE(listview->currentItem()->y(), 30.0);
 +    QTRY_COMPARE(listview->highlightItem()->y(), 30.0);
 +
 +    canvas->rootObject()->setProperty("delegateHeight", 20);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    for (int i = 5; i < 11; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY(item != 0);
 +        QTRY_COMPARE(item->y(), 150 + (i-5)*20.0);
 +    }
 +
 +    QTRY_COMPARE(listview->currentItem()->y(), 70.0);
 +    QTRY_COMPARE(listview->highlightItem()->y(), 70.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::resizeFirstDelegate()
 +{
 +    // QTBUG-20712: Content Y jumps constantly if first delegate height == 0
 +    // and other delegates have height > 0
 +
 +    QQuickView *canvas = createView();
 +
 +    // bug only occurs when all items in the model are visible
 +    QmlListModel model;
 +    for (int i = 0; i < 10; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QVERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QQuickItem *item = 0;
 +    for (int i = 0; i < model.count(); ++i) {
 +        item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY(item != 0);
 +        QCOMPARE(item->y(), i*20.0);
 +    }
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 0);
 +    item->setHeight(0);
 +
 +    // check the content y has not jumped up and down
 +    QCOMPARE(listview->contentY(), 0.0);
 +    QSignalSpy spy(listview, SIGNAL(contentYChanged()));
 +    QTest::qWait(100);
 +    QCOMPARE(spy.count(), 0);
 +
 +    for (int i = 1; i < model.count(); ++i) {
 +        item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY(item != 0);
 +        QTRY_COMPARE(item->y(), (i-1)*20.0);
 +    }
 +
 +
 +    // QTBUG-22014: refill doesn't clear items scrolling off the top of the
 +    // list if they follow a zero-sized delegate
 +
 +    for (int i = 0; i < 10; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +    QTRY_COMPARE(listview->count(), model.count());
 +
 +    item = findItem<QQuickItem>(contentItem, "wrapper", 1);
 +    QVERIFY(item);
 +    item->setHeight(0);
 +
 +    listview->setCurrentIndex(19);
 +    qApp->processEvents();
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // items 0-2 should have been deleted
 +    for (int i=0; i<3; i++) {
 +        QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", i));
 +    }
 +
 +    delete testObject;
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::QTBUG_16037()
 +{
 +    QQuickView *canvas = createView();
 +    canvas->show();
 +
 +    canvas->setSource(testFileUrl("qtbug16037.qml"));
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "listview");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QVERIFY(listview->contentHeight() <= 0.0);
 +
 +    QMetaObject::invokeMethod(canvas->rootObject(), "setModel");
 +
 +    QTRY_COMPARE(listview->contentHeight(), 80.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::indexAt_itemAt_data()
 +{
 +    QTest::addColumn<qreal>("x");
 +    QTest::addColumn<qreal>("y");
 +    QTest::addColumn<int>("index");
 +
 +    QTest::newRow("Item 0 - 0, 0") << 0. << 0. << 0;
 +    QTest::newRow("Item 0 - 0, 19") << 0. << 19. << 0;
 +    QTest::newRow("Item 0 - 239, 19") << 239. << 19. << 0;
 +    QTest::newRow("Item 1 - 0, 20") << 0. << 20. << 1;
 +    QTest::newRow("No Item - 240, 20") << 240. << 20. << -1;
 +}
 +
 +void tst_QQuickListView::indexAt_itemAt()
 +{
 +    QFETCH(qreal, x);
 +    QFETCH(qreal, y);
 +    QFETCH(int, index);
 +
 +    QQuickView *canvas = createView();
 +
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testObject", testObject);
 +
 +    canvas->setSource(testFileUrl("listviewtest.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QQuickItem *item = 0;
 +    if (index >= 0) {
 +        item = findItem<QQuickItem>(contentItem, "wrapper", index);
 +        QVERIFY(item);
 +    }
 +    QCOMPARE(listview->indexAt(x,y), index);
 +    QVERIFY(listview->itemAt(x,y) == item);
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::incrementalModel()
 +{
 +    QQuickView *canvas = createView();
 +
 +    IncrementalModel model;
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("displaylist.qml"));
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QTRY_COMPARE(listview->count(), 20);
 +
 +    listview->positionViewAtIndex(10, QQuickListView::Beginning);
 +
 +    QTRY_COMPARE(listview->count(), 25);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::onAdd()
 +{
 +    QFETCH(int, initialItemCount);
 +    QFETCH(int, itemsToAdd);
 +
 +    const int delegateHeight = 10;
 +    QaimModel model;
 +
 +    // these initial items should not trigger ListView.onAdd
 +    for (int i=0; i<initialItemCount; i++)
 +        model.addItem("dummy value", "dummy value");
 +
 +    QQuickView *canvas = createView();
 +    canvas->setGeometry(0,0,200, delegateHeight * (initialItemCount + itemsToAdd));
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("delegateHeight", delegateHeight);
 +    canvas->setSource(testFileUrl("attachedSignals.qml"));
 +
 +    QObject *object = canvas->rootObject();
 +    object->setProperty("width", canvas->width());
 +    object->setProperty("height", canvas->height());
 +    qApp->processEvents();
 +
 +    QList<QPair<QString, QString> > items;
 +    for (int i=0; i<itemsToAdd; i++)
 +        items << qMakePair(QString("value %1").arg(i), QString::number(i));
 +    model.addItems(items);
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    QVariantList result = object->property("addedDelegates").toList();
 +    QCOMPARE(result.count(), items.count());
 +    for (int i=0; i<items.count(); i++)
 +        QCOMPARE(result[i].toString(), items[i].first);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::onAdd_data()
 +{
 +    QTest::addColumn<int>("initialItemCount");
 +    QTest::addColumn<int>("itemsToAdd");
 +
 +    QTest::newRow("0, add 1") << 0 << 1;
 +    QTest::newRow("0, add 2") << 0 << 2;
 +    QTest::newRow("0, add 10") << 0 << 10;
 +
 +    QTest::newRow("1, add 1") << 1 << 1;
 +    QTest::newRow("1, add 2") << 1 << 2;
 +    QTest::newRow("1, add 10") << 1 << 10;
 +
 +    QTest::newRow("5, add 1") << 5 << 1;
 +    QTest::newRow("5, add 2") << 5 << 2;
 +    QTest::newRow("5, add 10") << 5 << 10;
 +}
 +
 +void tst_QQuickListView::onRemove()
 +{
 +    QFETCH(int, initialItemCount);
 +    QFETCH(int, indexToRemove);
 +    QFETCH(int, removeCount);
 +
 +    const int delegateHeight = 10;
 +    QaimModel model;
 +    for (int i=0; i<initialItemCount; i++)
 +        model.addItem(QString("value %1").arg(i), "dummy value");
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("delegateHeight", delegateHeight);
 +    canvas->setSource(testFileUrl("attachedSignals.qml"));
 +
 +    QObject *object = canvas->rootObject();
 +
 +    model.removeItems(indexToRemove, removeCount);
 +    QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
 +
 +    QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::onRemove_data()
 +{
 +    QTest::addColumn<int>("initialItemCount");
 +    QTest::addColumn<int>("indexToRemove");
 +    QTest::addColumn<int>("removeCount");
 +
 +    QTest::newRow("remove first") << 1 << 0 << 1;
 +    QTest::newRow("two items, remove first") << 2 << 0 << 1;
 +    QTest::newRow("two items, remove last") << 2 << 1 << 1;
 +    QTest::newRow("two items, remove all") << 2 << 0 << 2;
 +
 +    QTest::newRow("four items, remove first") << 4 << 0 << 1;
 +    QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
 +    QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
 +    QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
 +    QTest::newRow("four items, remove last") << 4 << 3 << 1;
 +    QTest::newRow("four items, remove all") << 4 << 0 << 4;
 +
 +    QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
 +    QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
 +    QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
 +}
 +
 +void tst_QQuickListView::rightToLeft()
 +{
 +    QQuickView *canvas = createView();
 +    canvas->setGeometry(0,0,640,320);
 +    canvas->setSource(testFileUrl("rightToLeft.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QVERIFY(canvas->rootObject() != 0);
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "view");
 +    QTRY_VERIFY(listview != 0);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QQuickVisualItemModel *model = canvas->rootObject()->findChild<QQuickVisualItemModel*>("itemModel");
 +    QTRY_VERIFY(model != 0);
 +
 +    QTRY_VERIFY(model->count() == 3);
 +    QTRY_COMPARE(listview->currentIndex(), 0);
 +
 +    // initial position at first item, right edge aligned
 +    QCOMPARE(listview->contentX(), -640.);
 +
 +    QQuickItem *item = findItem<QQuickItem>(contentItem, "item1");
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->x(), -100.0);
 +    QCOMPARE(item->height(), listview->height());
 +
 +    QQuickText *text = findItem<QQuickText>(contentItem, "text1");
 +    QTRY_VERIFY(text);
 +    QTRY_COMPARE(text->text(), QLatin1String("index: 0"));
 +
 +    listview->setCurrentIndex(2);
 +
 +    item = findItem<QQuickItem>(contentItem, "item3");
 +    QTRY_VERIFY(item);
 +    QTRY_COMPARE(item->x(), -540.0);
 +
 +    text = findItem<QQuickText>(contentItem, "text3");
 +    QTRY_VERIFY(text);
 +    QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
 +
 +    QCOMPARE(listview->contentX(), -640.);
 +
 +    // Ensure resizing maintains position relative to right edge
 +    qobject_cast<QQuickItem*>(canvas->rootObject())->setWidth(600);
 +    QTRY_COMPARE(listview->contentX(), -600.);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::test_mirroring()
 +{
 +    QQuickView *canvasA = createView();
 +    canvasA->setSource(testFileUrl("rightToLeft.qml"));
 +    QQuickListView *listviewA = findItem<QQuickListView>(canvasA->rootObject(), "view");
 +    QTRY_VERIFY(listviewA != 0);
 +
 +    QQuickView *canvasB = createView();
 +    canvasB->setSource(testFileUrl("rightToLeft.qml"));
 +    QQuickListView *listviewB = findItem<QQuickListView>(canvasB->rootObject(), "view");
 +    QTRY_VERIFY(listviewA != 0);
 +    qApp->processEvents();
 +
 +    QList<QString> objectNames;
 +    objectNames << "item1" << "item2"; // << "item3"
 +
 +    listviewA->setProperty("layoutDirection", Qt::LeftToRight);
 +    listviewB->setProperty("layoutDirection", Qt::RightToLeft);
 +    QCOMPARE(listviewA->layoutDirection(), listviewA->effectiveLayoutDirection());
 +
 +    // LTR != RTL
 +    foreach (const QString objectName, objectNames)
 +        QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
 +
 +    listviewA->setProperty("layoutDirection", Qt::LeftToRight);
 +    listviewB->setProperty("layoutDirection", Qt::LeftToRight);
 +
 +    // LTR == LTR
 +    foreach (const QString objectName, objectNames)
 +        QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
 +
 +    QVERIFY(listviewB->layoutDirection() == listviewB->effectiveLayoutDirection());
 +    QQuickItemPrivate::get(listviewB)->setLayoutMirror(true);
 +    QVERIFY(listviewB->layoutDirection() != listviewB->effectiveLayoutDirection());
 +
 +    // LTR != LTR+mirror
 +    foreach (const QString objectName, objectNames)
 +        QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
 +
 +    listviewA->setProperty("layoutDirection", Qt::RightToLeft);
 +
 +    // RTL == LTR+mirror
 +    foreach (const QString objectName, objectNames)
 +        QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
 +
 +    listviewB->setProperty("layoutDirection", Qt::RightToLeft);
 +
 +    // RTL != RTL+mirror
 +    foreach (const QString objectName, objectNames)
 +        QVERIFY(findItem<QQuickItem>(listviewA, objectName)->x() != findItem<QQuickItem>(listviewB, objectName)->x());
 +
 +    listviewA->setProperty("layoutDirection", Qt::LeftToRight);
 +
 +    // LTR == RTL+mirror
 +    foreach (const QString objectName, objectNames)
 +        QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
 +
 +    delete canvasA;
 +    delete canvasB;
 +}
 +
 +void tst_QQuickListView::margins()
 +{
 +    QQuickView *canvas = createView();
 +
 +    QaimModel model;
 +    for (int i = 0; i < 50; i++)
 +        model.addItem("Item" + QString::number(i), "");
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +
 +    canvas->setSource(testFileUrl("margins.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QCOMPARE(listview->contentY(), -30.);
 +    QCOMPARE(listview->yOrigin(), 0.);
 +
 +    // check end bound
 +    listview->positionViewAtEnd();
 +    qreal pos = listview->contentY();
 +    listview->setContentY(pos + 80);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    listview->returnToBounds();
 +    QTRY_COMPARE(listview->contentY(), pos + 50);
 +
 +    // remove item before visible and check that top margin is maintained
 +    // and yOrigin is updated
 +    listview->setContentY(100);
 +    model.removeItem(1);
 +    QTRY_COMPARE(listview->count(), model.count());
 +    listview->setContentY(-50);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    listview->returnToBounds();
 +    QCOMPARE(listview->yOrigin(), 20.);
 +    QTRY_COMPARE(listview->contentY(), -10.);
 +
 +    // reduce top margin
 +    listview->setTopMargin(20);
 +    QCOMPARE(listview->yOrigin(), 20.);
 +    QTRY_COMPARE(listview->contentY(), 0.);
 +
 +    // check end bound
 +    listview->positionViewAtEnd();
 +    pos = listview->contentY();
 +    listview->setContentY(pos + 80);
 +    listview->returnToBounds();
 +    QTRY_COMPARE(listview->contentY(), pos + 50);
 +
 +    // reduce bottom margin
 +    pos = listview->contentY();
 +    listview->setBottomMargin(40);
 +    QCOMPARE(listview->yOrigin(), 20.);
 +    QTRY_COMPARE(listview->contentY(), pos-10);
 +
 +    delete canvas;
 +}
 +
 +// QTBUG-24028
 +void tst_QQuickListView::marginsResize()
 +{
 +    QFETCH(QQuickListView::Orientation, orientation);
 +    QFETCH(Qt::LayoutDirection, layoutDirection);
 +    QFETCH(qreal, start);
 +    QFETCH(qreal, end);
 +
 +    QQuickView *canvas = createView();
 +
 +    canvas->setSource(testFileUrl("margins2.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "listview");
 +    QTRY_VERIFY(listview != 0);
 +
 +    listview->setOrientation(orientation);
 +    listview->setLayoutDirection(layoutDirection);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    // view is resized after componentCompleted - top margin should still be visible
 +    if (orientation == QQuickListView::Vertical)
 +        QCOMPARE(listview->contentY(), start);
 +    else
 +        QCOMPARE(listview->contentX(), start);
 +
 +    // move to last index and ensure bottom margin is visible.
 +    listview->setCurrentIndex(19);
 +    if (orientation == QQuickListView::Vertical)
 +        QTRY_COMPARE(listview->contentY(), end);
 +    else
 +        QTRY_COMPARE(listview->contentX(), end);
 +
 +    // back to top - top margin should be visible.
 +    listview->setCurrentIndex(0);
 +    if (orientation == QQuickListView::Vertical)
 +        QTRY_COMPARE(listview->contentY(), start);
 +    else
 +        QTRY_COMPARE(listview->contentX(), start);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::marginsResize_data()
 +{
 +    QTest::addColumn<QQuickListView::Orientation>("orientation");
 +    QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
 +    QTest::addColumn<qreal>("start");
 +    QTest::addColumn<qreal>("end");
 +
 +    QTest::newRow("vertical") << QQuickListView::Vertical << Qt::LeftToRight << -20.0 << 1020.0;
 +    QTest::newRow("horizontal") << QQuickListView::Horizontal << Qt::LeftToRight << -20.0 << 1020.0;
 +    QTest::newRow("horizontal, rtl") << QQuickListView::Horizontal << Qt::RightToLeft << -180.0 << -1220.0;
 +}
 +
 +void tst_QQuickListView::snapToItem_data()
 +{
 +    QTest::addColumn<QQuickListView::Orientation>("orientation");
 +    QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
 +    QTest::addColumn<int>("highlightRangeMode");
 +    QTest::addColumn<QPoint>("flickStart");
 +    QTest::addColumn<QPoint>("flickEnd");
 +    QTest::addColumn<qreal>("snapAlignment");
 +    QTest::addColumn<qreal>("endExtent");
 +    QTest::addColumn<qreal>("startExtent");
 +
 +    QTest::newRow("vertical, left to right") << QQuickListView::Vertical << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
 +
 +    QTest::newRow("horizontal, left to right") << QQuickListView::Horizontal << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
 +
 +    QTest::newRow("horizontal, right to left") << QQuickListView::Horizontal << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 << -240.0;
 +
 +    QTest::newRow("vertical, left to right, enforce range") << QQuickListView::Vertical << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
 +
 +    QTest::newRow("horizontal, left to right, enforce range") << QQuickListView::Horizontal << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
 +
 +    QTest::newRow("horizontal, right to left, enforce range") << QQuickListView::Horizontal << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 - 140.0 << -220.0;
 +}
 +
 +void tst_QQuickListView::snapToItem()
 +{
 +    QFETCH(QQuickListView::Orientation, orientation);
 +    QFETCH(Qt::LayoutDirection, layoutDirection);
 +    QFETCH(int, highlightRangeMode);
 +    QFETCH(QPoint, flickStart);
 +    QFETCH(QPoint, flickEnd);
 +    QFETCH(qreal, snapAlignment);
 +    QFETCH(qreal, endExtent);
 +    QFETCH(qreal, startExtent);
 +
 +    QQuickView *canvas = createView();
 +
 +    canvas->setSource(testFileUrl("snapToItem.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    listview->setOrientation(orientation);
 +    listview->setLayoutDirection(layoutDirection);
 +    listview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    // confirm that a flick hits an item boundary
 +    flick(canvas, flickStart, flickEnd, 180);
 +    QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
 +    if (orientation == QQuickListView::Vertical)
 +        QCOMPARE(qreal(fmod(listview->contentY(),80.0)), snapAlignment);
 +    else
 +        QCOMPARE(qreal(fmod(listview->contentX(),80.0)), snapAlignment);
 +
 +    // flick to end
 +    do {
 +        flick(canvas, flickStart, flickEnd, 180);
 +        QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
 +    } while (orientation == QQuickListView::Vertical
 +           ? !listview->isAtYEnd()
 +           : layoutDirection == Qt::LeftToRight ? !listview->isAtXEnd() : !listview->isAtXBeginning());
 +
 +    if (orientation == QQuickListView::Vertical)
 +        QCOMPARE(listview->contentY(), endExtent);
 +    else
 +        QCOMPARE(listview->contentX(), endExtent);
 +
 +    // flick to start
 +    do {
 +        flick(canvas, flickEnd, flickStart, 180);
 +        QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
 +    } while (orientation == QQuickListView::Vertical
 +           ? !listview->isAtYBeginning()
 +           : layoutDirection == Qt::LeftToRight ? !listview->isAtXBeginning() : !listview->isAtXEnd());
 +
 +    if (orientation == QQuickListView::Vertical)
 +        QCOMPARE(listview->contentY(), startExtent);
 +    else
 +        QCOMPARE(listview->contentX(), startExtent);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::qListModelInterface_items()
 +{
 +    items<QmlListModel>(testFileUrl("listviewtest.qml"), false);
 +}
 +
 +void tst_QQuickListView::qListModelInterface_package_items()
 +{
 +    items<QmlListModel>(testFileUrl("listviewtest-package.qml"), true);
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_items()
 +{
 +    items<QaimModel>(testFileUrl("listviewtest.qml"), false);
 +}
 +
 +void tst_QQuickListView::qListModelInterface_changed()
 +{
 +    changed<QmlListModel>(testFileUrl("listviewtest.qml"), false);
 +}
 +
 +void tst_QQuickListView::qListModelInterface_package_changed()
 +{
 +    changed<QmlListModel>(testFileUrl("listviewtest-package.qml"), true);
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_changed()
 +{
 +    changed<QaimModel>(testFileUrl("listviewtest.qml"), false);
 +}
 +
 +void tst_QQuickListView::qListModelInterface_inserted()
 +{
 +    inserted<QmlListModel>(testFileUrl("listviewtest.qml"));
 +}
 +
 +void tst_QQuickListView::qListModelInterface_package_inserted()
 +{
 +    inserted<QmlListModel>(testFileUrl("listviewtest-package.qml"));
 +}
 +
 +void tst_QQuickListView::qListModelInterface_inserted_more()
 +{
 +    inserted_more<QmlListModel>();
 +}
 +
 +void tst_QQuickListView::qListModelInterface_inserted_more_data()
 +{
 +    inserted_more_data();
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_inserted()
 +{
 +    inserted<QaimModel>(testFileUrl("listviewtest.qml"));
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_inserted_more()
 +{
 +    inserted_more<QaimModel>();
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_inserted_more_data()
 +{
 +    inserted_more_data();
 +}
 +
 +void tst_QQuickListView::qListModelInterface_removed()
 +{
 +    removed<QmlListModel>(testFileUrl("listviewtest.qml"), false);
 +    removed<QmlListModel>(testFileUrl("listviewtest.qml"), true);
 +}
 +
 +void tst_QQuickListView::qListModelInterface_removed_more()
 +{
 +    removed_more<QmlListModel>(testFileUrl("listviewtest.qml"));
 +}
 +
 +void tst_QQuickListView::qListModelInterface_removed_more_data()
 +{
 +    removed_more_data();
 +}
 +
 +void tst_QQuickListView::qListModelInterface_package_removed()
 +{
 +    removed<QmlListModel>(testFileUrl("listviewtest-package.qml"), false);
 +    removed<QmlListModel>(testFileUrl("listviewtest-package.qml"), true);
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_removed()
 +{
 +    removed<QaimModel>(testFileUrl("listviewtest.qml"), false);
 +    removed<QaimModel>(testFileUrl("listviewtest.qml"), true);
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_removed_more()
 +{
 +    removed_more<QaimModel>(testFileUrl("listviewtest.qml"));
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_removed_more_data()
 +{
 +    removed_more_data();
 +}
 +
 +void tst_QQuickListView::qListModelInterface_moved()
 +{
 +    moved<QmlListModel>(testFileUrl("listviewtest.qml"));
 +}
 +
 +void tst_QQuickListView::qListModelInterface_moved_data()
 +{
 +    moved_data();
 +}
 +
 +void tst_QQuickListView::qListModelInterface_package_moved()
 +{
 +    moved<QmlListModel>(testFileUrl("listviewtest-package.qml"));
 +}
 +
 +void tst_QQuickListView::qListModelInterface_package_moved_data()
 +{
 +    moved_data();
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_moved()
 +{
 +    moved<QaimModel>(testFileUrl("listviewtest.qml"));
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_moved_data()
 +{
 +    moved_data();
 +}
 +
 +void tst_QQuickListView::qListModelInterface_clear()
 +{
 +    clear<QmlListModel>(testFileUrl("listviewtest.qml"));
 +}
 +
 +void tst_QQuickListView::qListModelInterface_package_clear()
 +{
 +    clear<QmlListModel>(testFileUrl("listviewtest-package.qml"));
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_clear()
 +{
 +    clear<QaimModel>(testFileUrl("listviewtest.qml"));
 +}
 +
 +void tst_QQuickListView::qListModelInterface_sections()
 +{
 +    sections<QmlListModel>(testFileUrl("listview-sections.qml"));
 +}
 +
 +void tst_QQuickListView::qListModelInterface_package_sections()
 +{
 +    sections<QmlListModel>(testFileUrl("listview-sections-package.qml"));
 +}
 +
 +void tst_QQuickListView::qAbstractItemModel_sections()
 +{
 +    sections<QaimModel>(testFileUrl("listview-sections.qml"));
 +}
 +
 +void tst_QQuickListView::creationContext()
 +{
 +    QQuickView canvas;
 +    canvas.setGeometry(0,0,240,320);
 +    canvas.setSource(testFileUrl("creationContext.qml"));
 +    qApp->processEvents();
 +
 +    QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
 +    QVERIFY(rootItem);
 +    QVERIFY(rootItem->property("count").toInt() > 0);
 +
 +    QQuickItem *item;
 +    QVERIFY(item = rootItem->findChild<QQuickItem *>("listItem"));
 +    QCOMPARE(item->property("text").toString(), QString("Hello!"));
 +    QVERIFY(item = rootItem->findChild<QQuickItem *>("header"));
 +    QCOMPARE(item->property("text").toString(), QString("Hello!"));
 +    QVERIFY(item = rootItem->findChild<QQuickItem *>("footer"));
 +    QCOMPARE(item->property("text").toString(), QString("Hello!"));
 +    QVERIFY(item = rootItem->findChild<QQuickItem *>("section"));
 +    QCOMPARE(item->property("text").toString(), QString("Hello!"));
 +}
 +
 +void tst_QQuickListView::QTBUG_21742()
 +{
 +    QQuickView canvas;
 +    canvas.setGeometry(0,0,200,200);
 +    canvas.setSource(testFileUrl("qtbug-21742.qml"));
 +    qApp->processEvents();
 +
 +    QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
 +    QVERIFY(rootItem);
 +    QCOMPARE(rootItem->property("count").toInt(), 1);
 +}
 +
 +void tst_QQuickListView::asynchronous()
 +{
 +    QQuickView *canvas = createView();
 +    canvas->show();
 +    QQmlIncubationController controller;
 +    canvas->engine()->setIncubationController(&controller);
 +
 +    canvas->setSource(testFileUrl("asyncloader.qml"));
 +
 +    QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
 +    QVERIFY(rootObject);
 +
 +    QQuickListView *listview = 0;
 +    while (!listview) {
 +        bool b = false;
 +        controller.incubateWhile(&b);
 +        listview = rootObject->findChild<QQuickListView*>("view");
 +    }
 +
 +    // items will be created one at a time
 +    for (int i = 0; i < 8; ++i) {
 +        QVERIFY(findItem<QQuickItem>(listview, "wrapper", i) == 0);
 +        QQuickItem *item = 0;
 +        while (!item) {
 +            bool b = false;
 +            controller.incubateWhile(&b);
 +            item = findItem<QQuickItem>(listview, "wrapper", i);
 +        }
 +    }
 +
 +    {
 +        bool b = true;
 +        controller.incubateWhile(&b);
 +    }
 +
 +    // verify positioning
 +    QQuickItem *contentItem = listview->contentItem();
 +    for (int i = 0; i < 8; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QTRY_COMPARE(item->y(), i*50.0);
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::snapOneItem_data()
 +{
 +    QTest::addColumn<QQuickListView::Orientation>("orientation");
 +    QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
 +    QTest::addColumn<int>("highlightRangeMode");
 +    QTest::addColumn<QPoint>("flickStart");
 +    QTest::addColumn<QPoint>("flickEnd");
 +    QTest::addColumn<qreal>("snapAlignment");
 +    QTest::addColumn<qreal>("endExtent");
 +    QTest::addColumn<qreal>("startExtent");
 +
 +    QTest::newRow("vertical, left to right") << QQuickListView::Vertical << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(20, 200) << QPoint(20, 20) << 180.0 << 560.0 << 0.0;
 +
 +    QTest::newRow("horizontal, left to right") << QQuickListView::Horizontal << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(200, 20) << QPoint(20, 20) << 180.0 << 560.0 << 0.0;
 +
 +    QTest::newRow("horizontal, right to left") << QQuickListView::Horizontal << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
 +        << QPoint(20, 20) << QPoint(200, 20) << -420.0 << -560.0 - 240.0 << -240.0;
 +
 +    QTest::newRow("vertical, left to right, enforce range") << QQuickListView::Vertical << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(20, 200) << QPoint(20, 20) << 180.0 << 580.0 << -20.0;
 +
 +    QTest::newRow("horizontal, left to right, enforce range") << QQuickListView::Horizontal << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(200, 20) << QPoint(20, 20) << 180.0 << 580.0 << -20.0;
 +
 +    QTest::newRow("horizontal, right to left, enforce range") << QQuickListView::Horizontal << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
 +        << QPoint(20, 20) << QPoint(200, 20) << -420.0 << -580.0 - 240.0 << -220.0;
 +}
 +
 +void tst_QQuickListView::snapOneItem()
 +{
 +    QFETCH(QQuickListView::Orientation, orientation);
 +    QFETCH(Qt::LayoutDirection, layoutDirection);
 +    QFETCH(int, highlightRangeMode);
 +    QFETCH(QPoint, flickStart);
 +    QFETCH(QPoint, flickEnd);
 +    QFETCH(qreal, snapAlignment);
 +    QFETCH(qreal, endExtent);
 +    QFETCH(qreal, startExtent);
 +
 +#ifdef Q_OS_MAC
 +    // This test seems to be unreliable - different test data fails on different runs
 +    QSKIP("QTBUG-24338");
 +#endif
 +
 +    QQuickView *canvas = createView();
 +
 +    canvas->setSource(testFileUrl("snapOneItem.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +
 +    listview->setOrientation(orientation);
 +    listview->setLayoutDirection(layoutDirection);
 +    listview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    QQuickItem *contentItem = listview->contentItem();
 +    QTRY_VERIFY(contentItem != 0);
 +
 +    QSignalSpy currentIndexSpy(listview, SIGNAL(currentIndexChanged()));
 +
 +    // confirm that a flick hits the next item boundary
 +    flick(canvas, flickStart, flickEnd, 180);
 +    QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
 +    if (orientation == QQuickListView::Vertical)
 +        QCOMPARE(listview->contentY(), snapAlignment);
 +    else
 +        QCOMPARE(listview->contentX(), snapAlignment);
 +
 +    if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
 +        QCOMPARE(listview->currentIndex(), 1);
 +        QCOMPARE(currentIndexSpy.count(), 1);
 +    }
 +
 +    // flick to end
 +    do {
 +        flick(canvas, flickStart, flickEnd, 180);
 +        QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
 +    } while (orientation == QQuickListView::Vertical
 +           ? !listview->isAtYEnd()
 +           : layoutDirection == Qt::LeftToRight ? !listview->isAtXEnd() : !listview->isAtXBeginning());
 +
 +    if (orientation == QQuickListView::Vertical)
 +        QCOMPARE(listview->contentY(), endExtent);
 +    else
 +        QCOMPARE(listview->contentX(), endExtent);
 +
 +    if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
 +        QCOMPARE(listview->currentIndex(), 3);
 +        QCOMPARE(currentIndexSpy.count(), 3);
 +    }
 +
 +    // flick to start
 +    do {
 +        flick(canvas, flickEnd, flickStart, 180);
 +        QTRY_VERIFY(listview->isMoving() == false); // wait until it stops
 +    } while (orientation == QQuickListView::Vertical
 +           ? !listview->isAtYBeginning()
 +           : layoutDirection == Qt::LeftToRight ? !listview->isAtXBeginning() : !listview->isAtXEnd());
 +
 +    if (orientation == QQuickListView::Vertical)
 +        QCOMPARE(listview->contentY(), startExtent);
 +    else
 +        QCOMPARE(listview->contentX(), startExtent);
 +
 +    if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
 +        QCOMPARE(listview->currentIndex(), 0);
 +        QCOMPARE(currentIndexSpy.count(), 6);
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::unrequestedVisibility()
 +{
 +    QmlListModel model;
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("Item" + QString::number(i), QString::number(i));
 +
 +    QQuickView *canvas = new QQuickView(0);
 +    canvas->setGeometry(0,0,240,320);
 +
 +    QQmlContext *ctxt = canvas->rootContext();
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testWrap", QVariant(false));
 +
 +    canvas->setSource(testFileUrl("unrequestedItems.qml"));
 +    canvas->show();
 +    qApp->processEvents();
 +
 +    QQuickListView *leftview = findItem<QQuickListView>(canvas->rootObject(), "leftList");
 +    QTRY_VERIFY(leftview != 0);
 +
 +    QQuickListView *rightview = findItem<QQuickListView>(canvas->rootObject(), "rightList");
 +    QTRY_VERIFY(rightview != 0);
 +
 +    QQuickItem *leftContent = leftview->contentItem();
 +    QTRY_VERIFY(leftContent != 0);
 +
 +    QQuickItem *rightContent = rightview->contentItem();
 +    QTRY_VERIFY(rightContent != 0);
 +
 +    rightview->setCurrentIndex(20);
 +
 +    QTRY_COMPARE(leftview->contentY(), 0.0);
 +    QTRY_COMPARE(rightview->contentY(), 100.0);
 +
 +    QQuickItem *item;
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 19));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 19));
 +    QCOMPARE(item->isVisible(), true);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 16));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 17));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 3));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 4));
 +    QCOMPARE(item->isVisible(), true);
 +
 +    rightview->setCurrentIndex(0);
 +
 +    QTRY_COMPARE(leftview->contentY(), 0.0);
 +    QTRY_COMPARE(rightview->contentY(), 0.0);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
 +    QTRY_COMPARE(item->isVisible(), true);
 +
 +    QVERIFY(!findItem<QQuickItem>(leftContent, "wrapper", 19));
 +    QVERIFY(!findItem<QQuickItem>(rightContent, "wrapper", 19));
 +
 +    leftview->setCurrentIndex(20);
 +
 +    QTRY_COMPARE(leftview->contentY(), 100.0);
 +    QTRY_COMPARE(rightview->contentY(), 0.0);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
 +    QTRY_COMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), true);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 19));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 19));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 16));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 17));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    model.moveItems(19, 1, 1);
 +    QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
 +
 +    QTRY_VERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
 +    QCOMPARE(item->isVisible(), true);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 19));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 19));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 16));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 17));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    model.moveItems(3, 4, 1);
 +    QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 16));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 17));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    model.moveItems(4, 3, 1);
 +    QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 16));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 17));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    model.moveItems(16, 17, 1);
 +    QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 16));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 17));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    model.moveItems(17, 16, 1);
 +    QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
 +
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
 +    QCOMPARE(item->isVisible(), false);
 +    QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 16));
 +    QCOMPARE(item->isVisible(), true);
 +    QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 17));
 +    QCOMPARE(item->isVisible(), false);
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::populateTransitions()
 +{
 +    QFETCH(bool, staticallyPopulate);
 +    QFETCH(bool, dynamicallyPopulate);
 +    QFETCH(bool, usePopulateTransition);
 +
 +    QPointF transitionFrom(-50, -50);
 +    QPointF transitionVia(100, 100);
 +    QaimModel model_transitionFrom;
 +    QaimModel model_transitionVia;
 +
 +    QaimModel model;
 +    if (staticallyPopulate) {
 +        for (int i = 0; i < 30; i++)
 +            model.addItem("item" + QString::number(i), "");
 +    }
 +
 +    QQuickView *canvas = createView();
 +    canvas->rootContext()->setContextProperty("testModel", &model);
 +    canvas->rootContext()->setContextProperty("testObject", new TestObject(canvas->rootContext()));
 +    canvas->rootContext()->setContextProperty("usePopulateTransition", usePopulateTransition);
 +    canvas->rootContext()->setContextProperty("dynamicallyPopulate", dynamicallyPopulate);
 +    canvas->rootContext()->setContextProperty("transitionFrom", transitionFrom);
 +    canvas->rootContext()->setContextProperty("transitionVia", transitionVia);
 +    canvas->rootContext()->setContextProperty("model_transitionFrom", &model_transitionFrom);
 +    canvas->rootContext()->setContextProperty("model_transitionVia", &model_transitionVia);
 +    canvas->setSource(testFileUrl("populateTransitions.qml"));
 +    canvas->show();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QVERIFY(listview);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QVERIFY(contentItem);
 +
 +    if (staticallyPopulate || dynamicallyPopulate) {
 +        // check the populate transition is run
 +        if (usePopulateTransition) {
 +            QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(), 17);
 +        } else {
 +            QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +            QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(), 0);
 +        }
 +        QTRY_COMPARE(listview->property("countAddTransitions").toInt(), 0);
 +    } else {
 +        QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    }
 +
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    if (usePopulateTransition)
 +        QCOMPARE(itemCount, listview->property("countPopulateTransitions").toInt());
 +    for (int i=0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QTRY_COMPARE(item->x(), 0.0);
 +        QTRY_COMPARE(item->y(), i*20.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    // add an item and check this is done with add trantion, not populate
 +    model.insertItem(0, "another item", "");
 +    QTRY_COMPARE(listview->property("countAddTransitions").toInt(), 1);
 +    QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(),
 +                 (usePopulateTransition && (staticallyPopulate || dynamicallyPopulate)) ? 17 : 0);
 +
 +    // clear the model
 +    canvas->rootContext()->setContextProperty("testModel", QVariant());
 +    QTRY_COMPARE(listview->count(), 0);
 +    QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper").count(), 0);
 +    listview->setProperty("countPopulateTransitions", 0);
 +    listview->setProperty("countAddTransitions", 0);
 +
 +    // set to a valid model and check populate transition is run a second time
 +    model.clear();
 +    for (int i = 0; i < 30; i++)
 +        model.addItem("item" + QString::number(i), "");
 +    canvas->rootContext()->setContextProperty("testModel", &model);
 +    QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(), usePopulateTransition ? 17 : 0);
 +    QTRY_COMPARE(listview->property("countAddTransitions").toInt(), 0);
 +
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    if (usePopulateTransition)
 +        QCOMPARE(itemCount, listview->property("countPopulateTransitions").toInt());
 +    for (int i=0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QTRY_COMPARE(item->x(), 0.0);
 +        QTRY_COMPARE(item->y(), i*20.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    // reset model and check populate transition is run again
 +    listview->setProperty("countPopulateTransitions", 0);
 +    listview->setProperty("countAddTransitions", 0);
 +    model.reset();
 +    QTRY_COMPARE(listview->property("countPopulateTransitions").toInt(), usePopulateTransition ? 17 : 0);
 +    QTRY_COMPARE(listview->property("countAddTransitions").toInt(), 0);
 +
 +    itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    if (usePopulateTransition)
 +        QCOMPARE(itemCount, listview->property("countPopulateTransitions").toInt());
 +    for (int i=0; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QTRY_COMPARE(item->x(), 0.0);
 +        QTRY_COMPARE(item->y(), i*20.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_QQuickListView::populateTransitions_data()
 +{
 +    QTest::addColumn<bool>("staticallyPopulate");
 +    QTest::addColumn<bool>("dynamicallyPopulate");
 +    QTest::addColumn<bool>("usePopulateTransition");
 +
 +    QTest::newRow("static") << true << false << true;
 +    QTest::newRow("static, no populate") << true << false << false;
 +
 +    QTest::newRow("dynamic") << false << true << true;
 +    QTest::newRow("dynamic, no populate") << false << true << false;
 +
 +    QTest::newRow("empty to start with") << false << false << true;
 +    QTest::newRow("empty to start with, no populate") << false << false << false;
 +}
 +
 +void tst_QQuickListView::addTransitions()
 +{
 +    QFETCH(int, initialItemCount);
 +    QFETCH(bool, shouldAnimateTargets);
 +    QFETCH(qreal, contentY);
 +    QFETCH(int, insertionIndex);
 +    QFETCH(int, insertionCount);
 +    QFETCH(ListRange, expectedDisplacedIndexes);
 +
 +    // added items should start here
 +    QPointF targetItems_transitionFrom(-50, -50);
 +
 +    // displaced items should pass through this point
 +    QPointF displacedItems_transitionVia(100, 100);
 +
 +    QaimModel model;
 +    for (int i = 0; i < initialItemCount; i++)
 +        model.addItem("Original item" + QString::number(i), "");
 +    QaimModel model_targetItems_transitionFrom;
 +    QaimModel model_displacedItems_transitionVia;
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
 +    ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
 +    ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
 +    ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
 +    ctxt->setContextProperty("testObject", testObject);
 +    canvas->setSource(testFileUrl("addTransitions.qml"));
 +    canvas->show();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    if (contentY != 0) {
 +        listview->setContentY(contentY);
 +        QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    }
 +
 +    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
 +
 +    // only target items that will become visible should be animated
 +    QList<QPair<QString, QString> > newData;
 +    QList<QPair<QString, QString> > expectedTargetData;
 +    QList<int> targetIndexes;
 +    if (shouldAnimateTargets) {
 +        for (int i=insertionIndex; i<insertionIndex+insertionCount; i++) {
 +            newData << qMakePair(QString("New item %1").arg(i), QString(""));
 +
 +            if (i >= contentY / 20 && i < (contentY + listview->height()) / 20) {  // only grab visible items
 +                expectedTargetData << newData.last();
 +                targetIndexes << i;
 +            }
 +        }
 +        QVERIFY(expectedTargetData.count() > 0);
 +    }
 +
 +    // start animation
 +    if (!newData.isEmpty()) {
 +        model.insertItems(insertionIndex, newData);
 +        QTRY_COMPARE(model.count(), listview->count());
 +    }
 +
 +    QList<QQuickItem *> targetItems = findItems<QQuickItem>(contentItem, "wrapper", targetIndexes);
 +
 +    if (shouldAnimateTargets) {
 +        QTRY_COMPARE(listview->property("targetTransitionsDone").toInt(), expectedTargetData.count());
 +        QTRY_COMPARE(listview->property("displaceTransitionsDone").toInt(),
 +                     expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0);
 +
 +        // check the target and displaced items were animated
 +        model_targetItems_transitionFrom.matchAgainst(expectedTargetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos");
 +        model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim");
 +
 +        // check attached properties
 +        matchItemsAndIndexes(listview->property("targetTrans_items").toMap(), model, targetIndexes);
 +        matchIndexLists(listview->property("targetTrans_targetIndexes").toList(), targetIndexes);
 +        matchItemLists(listview->property("targetTrans_targetItems").toList(), targetItems);
 +        if (expectedDisplacedIndexes.isValid()) {
 +            // adjust expectedDisplacedIndexes to their final values after the move
 +            QList<int> displacedIndexes = adjustIndexesForAddDisplaced(expectedDisplacedIndexes.indexes, insertionIndex, insertionCount);
 +            matchItemsAndIndexes(listview->property("displacedTrans_items").toMap(), model, displacedIndexes);
 +            matchIndexLists(listview->property("displacedTrans_targetIndexes").toList(), targetIndexes);
 +            matchItemLists(listview->property("displacedTrans_targetItems").toList(), targetItems);
 +        }
 +
 +    } else {
 +        QTRY_COMPARE(model_targetItems_transitionFrom.count(), 0);
 +        QTRY_COMPARE(model_displacedItems_transitionVia.count(), 0);
 +    }
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    int firstVisibleIndex = -1;
 +    int itemCount = items.count();
 +    for (int i=0; i<items.count(); i++) {
 +        if (items[i]->y() >= contentY) {
 +            QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +            firstVisibleIndex = e.evaluate().toInt();
 +            break;
 +        }
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // verify all items moved to the correct final positions
 +    for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QTRY_COMPARE(item->y(), i*20.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::addTransitions_data()
 +{
 +    QTest::addColumn<int>("initialItemCount");
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<bool>("shouldAnimateTargets");
 +    QTest::addColumn<int>("insertionIndex");
 +    QTest::addColumn<int>("insertionCount");
 +    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
 +
 +    // if inserting before visible index, items should not appear or animate in, even if there are > 1 new items
 +    QTest::newRow("insert 1, just before start")
 +            << 30 << 20.0 << false
 +            << 0 << 1 << ListRange();
 +    QTest::newRow("insert 1, way before start")
 +            << 30 << 20.0 << false
 +            << 0 << 1 << ListRange();
 +    QTest::newRow("insert multiple, just before start")
 +            << 30 << 100.0 << false
 +            << 0 << 3 << ListRange();
 +    QTest::newRow("insert multiple, way before start")
 +            << 30 << 100.0 << false
 +            << 0 << 3 << ListRange();
 +
 +    QTest::newRow("insert 1 at start")
 +            << 30 << 0.0 << true
 +            << 0 << 1 << ListRange(0, 15);
 +    QTest::newRow("insert multiple at start")
 +            << 30 << 0.0 << true
 +            << 0 << 3 << ListRange(0, 15);
 +    QTest::newRow("insert 1 at start, content y not 0")
 +            << 30 << 40.0 << true  // first visible is index 2, so translate the displaced indexes by 2
 +            << 2 << 1 << ListRange(0 + 2, 15 + 2);
 +    QTest::newRow("insert multiple at start, content y not 0")
 +            << 30 << 40.0 << true    // first visible is index 2
 +            << 2 << 3 << ListRange(0 + 2, 15 + 2);
 +
 +    QTest::newRow("insert 1 at start, to empty list")
 +            << 0 << 0.0 << true
 +            << 0 << 1 << ListRange();
 +    QTest::newRow("insert multiple at start, to empty list")
 +            << 0 << 0.0 << true
 +            << 0 << 3 << ListRange();
 +
 +    QTest::newRow("insert 1 at middle")
 +            << 30 << 0.0 << true
 +            << 5 << 1 << ListRange(5, 15);
 +    QTest::newRow("insert multiple at middle")
 +            << 30 << 0.0 << true
 +            << 5 << 3 << ListRange(5, 15);
 +
 +    QTest::newRow("insert 1 at bottom")
 +            << 30 << 0.0 << true
 +            << 15 << 1 << ListRange(15, 15);
 +    QTest::newRow("insert multiple at bottom")
 +            << 30 << 0.0 << true
 +            << 15 << 3 << ListRange(15, 15);
 +    QTest::newRow("insert 1 at bottom, content y not 0")
 +            << 30 << 20.0 * 3 << true
 +            << 15 + 3 << 1 << ListRange(15 + 3, 15 + 3);
 +    QTest::newRow("insert multiple at bottom, content y not 0")
 +            << 30 << 20.0 * 3 << true
 +            << 15 + 3 << 3 << ListRange(15 + 3, 15 + 3);
 +
 +    // items added after the last visible will not be animated in, since they
 +    // do not appear in the final view
 +    QTest::newRow("insert 1 after end")
 +            << 30 << 0.0 << false
 +            << 17 << 1 << ListRange();
 +    QTest::newRow("insert multiple after end")
 +            << 30 << 0.0 << false
 +            << 17 << 3 << ListRange();
 +}
 +
 +void tst_QQuickListView::moveTransitions()
 +{
 +    QFETCH(int, initialItemCount);
 +    QFETCH(qreal, contentY);
 +    QFETCH(qreal, itemsOffsetAfterMove);
 +    QFETCH(int, moveFrom);
 +    QFETCH(int, moveTo);
 +    QFETCH(int, moveCount);
 +    QFETCH(ListRange, expectedDisplacedIndexes);
 +
 +    // target and displaced items should pass through these points
 +    QPointF targetItems_transitionVia(-50, 50);
 +    QPointF displacedItems_transitionVia(100, 100);
 +
 +    QaimModel model;
 +    for (int i = 0; i < initialItemCount; i++)
 +        model.addItem("Original item" + QString::number(i), "");
 +    QaimModel model_targetItems_transitionVia;
 +    QaimModel model_displacedItems_transitionVia;
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("model_targetItems_transitionVia", &model_targetItems_transitionVia);
 +    ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
 +    ctxt->setContextProperty("targetItems_transitionVia", targetItems_transitionVia);
 +    ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
 +    ctxt->setContextProperty("testObject", testObject);
 +    canvas->setSource(testFileUrl("moveTransitions.qml"));
 +    canvas->show();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QQuickText *name;
 +
 +    if (contentY != 0) {
 +        listview->setContentY(contentY);
 +        QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    }
 +
 +    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
 +
 +    // Items moving to *or* from visible positions should be animated.
 +    // Otherwise, they should not be animated.
 +    QList<QPair<QString, QString> > expectedTargetData;
 +    QList<int> targetIndexes;
 +    for (int i=moveFrom; i<moveFrom+moveCount; i++) {
 +        int toIndex = moveTo + (i - moveFrom);
 +        if (i <= (contentY + listview->height()) / 20
 +                || toIndex < (contentY + listview->height()) / 20) {
 +            expectedTargetData << qMakePair(model.name(i), model.number(i));
 +            targetIndexes << i;
 +        }
 +    }
 +    // ViewTransition.index provides the indices that items are moving to, not from
 +    targetIndexes = adjustIndexesForMove(targetIndexes, moveFrom, moveTo, moveCount);
 +
 +    // start animation
 +    model.moveItems(moveFrom, moveTo, moveCount);
 +
 +    QTRY_COMPARE(listview->property("targetTransitionsDone").toInt(), expectedTargetData.count());
 +    QTRY_COMPARE(listview->property("displaceTransitionsDone").toInt(),
 +                 expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0);
 +
 +    QList<QQuickItem *> targetItems = findItems<QQuickItem>(contentItem, "wrapper", targetIndexes);
 +
 +    // check the target and displaced items were animated
 +    model_targetItems_transitionVia.matchAgainst(expectedTargetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos");
 +    model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim");
 +
 +    // check attached properties
 +    matchItemsAndIndexes(listview->property("targetTrans_items").toMap(), model, targetIndexes);
 +    matchIndexLists(listview->property("targetTrans_targetIndexes").toList(), targetIndexes);
 +    matchItemLists(listview->property("targetTrans_targetItems").toList(), targetItems);
 +    if (expectedDisplacedIndexes.isValid()) {
 +        // adjust expectedDisplacedIndexes to their final values after the move
 +        QList<int> displacedIndexes = adjustIndexesForMove(expectedDisplacedIndexes.indexes, moveFrom, moveTo, moveCount);
 +        matchItemsAndIndexes(listview->property("displacedTrans_items").toMap(), model, displacedIndexes);
 +        matchIndexLists(listview->property("displacedTrans_targetIndexes").toList(), targetIndexes);
 +        matchItemLists(listview->property("displacedTrans_targetItems").toList(), targetItems);
 +    }
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    int firstVisibleIndex = -1;
 +    for (int i=0; i<items.count(); i++) {
 +        if (items[i]->y() >= contentY) {
 +            QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +            firstVisibleIndex = e.evaluate().toInt();
 +            break;
 +        }
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // verify all items moved to the correct final positions
 +    int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
 +    for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
 +        name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::moveTransitions_data()
 +{
 +    QTest::addColumn<int>("initialItemCount");
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<qreal>("itemsOffsetAfterMove");
 +    QTest::addColumn<int>("moveFrom");
 +    QTest::addColumn<int>("moveTo");
 +    QTest::addColumn<int>("moveCount");
 +    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
 +
 +    // when removing from above the visible, all items shift down depending on how many
 +    // items have been removed from above the visible
 +    QTest::newRow("move from above view, outside visible items, move 1") << 30 << 4*20.0 << 20.0
 +            << 1 << 10 << 1 << ListRange(11, 15+4);
 +    QTest::newRow("move from above view, outside visible items, move 1 (first item)") << 30 << 4*20.0 << 20.0
 +            << 0 << 10 << 1 << ListRange(11, 15+4);
 +    QTest::newRow("move from above view, outside visible items, move multiple") << 30 << 4*20.0 << 2*20.0
 +            << 1 << 10 << 2 << ListRange(12, 15+4);
 +    QTest::newRow("move from above view, outside visible items, move multiple (first item)") << 30 << 4*20.0 << 3*20.0
 +            << 0 << 10 << 3 << ListRange(13, 15+4);
 +    QTest::newRow("move from above view, mix of visible/non-visible") << 30 << 4*20.0 << 3*20.0
 +            << 1 << 10 << 5 << ListRange(6, 14) + ListRange(15, 15+4);
 +    QTest::newRow("move from above view, mix of visible/non-visible (move first)") << 30 << 4*20.0 << 4*20.0
 +            << 0 << 10 << 5 << ListRange(5, 14) + ListRange(15, 15+4);
 +
 +    QTest::newRow("move within view, move 1 down") << 30 << 0.0 << 0.0
 +            << 1 << 10 << 1 << ListRange(2, 10);
 +    QTest::newRow("move within view, move 1 down, move first item") << 30 << 0.0 << 0.0
 +            << 0 << 10 << 1 << ListRange(1, 10);
 +    QTest::newRow("move within view, move 1 down, move first item, contentY not 0") << 30 << 4*20.0 << 0.0
 +            << 0+4 << 10+4 << 1 << ListRange(1+4, 10+4);
 +    QTest::newRow("move within view, move 1 down, to last item") << 30 << 0.0 << 0.0
 +            << 10 << 15 << 1 << ListRange(11, 15);
 +    QTest::newRow("move within view, move first->last") << 30 << 0.0 << 0.0
 +            << 0 << 15 << 1 << ListRange(1, 15);
 +
 +    QTest::newRow("move within view, move multiple down") << 30 << 0.0 << 0.0
 +            << 1 << 10 << 3 << ListRange(4, 12);
 +    QTest::newRow("move within view, move multiple down, move first item") << 30 << 0.0 << 0.0
 +            << 0 << 10 << 3 << ListRange(3, 12);
 +    QTest::newRow("move within view, move multiple down, move first item, contentY not 0") << 30 << 4*20.0 << 0.0
 +            << 0+4 << 10+4 << 3 << ListRange(3+4, 12+4);
 +    QTest::newRow("move within view, move multiple down, displace last item") << 30 << 0.0 << 0.0
 +            << 5 << 13 << 3 << ListRange(8, 15);
 +    QTest::newRow("move within view, move multiple down, move first->last") << 30 << 0.0 << 0.0
 +            << 0 << 13 << 3 << ListRange(3, 15);
 +
 +    QTest::newRow("move within view, move 1 up") << 30 << 0.0 << 0.0
 +            << 10 << 1 << 1 << ListRange(1, 9);
 +    QTest::newRow("move within view, move 1 up, move to first index") << 30 << 0.0 << 0.0
 +            << 10 << 0 << 1 << ListRange(0, 9);
 +    QTest::newRow("move within view, move 1 up, move to first index, contentY not 0") << 30 << 4*20.0 << 0.0
 +            << 10+4 << 0+4 << 1 << ListRange(0+4, 9+4);
 +    QTest::newRow("move within view, move 1 up, move to first index, contentY not on item border") << 30 << 4*20.0 - 10 << 0.0
 +            << 10+4 << 0+4 << 1 << ListRange(0+4, 9+4);
 +    QTest::newRow("move within view, move 1 up, move last item") << 30 << 0.0 << 0.0
 +            << 15 << 10 << 1 << ListRange(10, 14);
 +    QTest::newRow("move within view, move 1 up, move last->first") << 30 << 0.0 << 0.0
 +            << 15 << 0 << 1 << ListRange(0, 14);
 +
 +    QTest::newRow("move within view, move multiple up") << 30 << 0.0 << 0.0
 +            << 10 << 1 << 3 << ListRange(1, 9);
 +    QTest::newRow("move within view, move multiple up, move to first index") << 30 << 0.0 << 0.0
 +            << 10 << 0 << 3 << ListRange(0, 9);
 +    QTest::newRow("move within view, move multiple up, move to first index, contentY not 0") << 30 << 4*20.0 << 0.0
 +            << 10+4 << 0+4 << 3 << ListRange(0+4, 9+4);
 +    QTest::newRow("move within view, move multiple up, move last item") << 30 << 0.0 << 0.0
 +            << 13 << 5 << 3 << ListRange(5, 12);
 +    QTest::newRow("move within view, move multiple up, move last->first") << 30 << 0.0 << 0.0
 +            << 13 << 0 << 3 << ListRange(0, 12);
 +
 +    QTest::newRow("move from below view, move 1 up, move to top") << 30 << 0.0 << 0.0
 +            << 20 << 0 << 1 << ListRange(0, 15);
 +    QTest::newRow("move from below view, move 1 up, move to top, contentY not 0") << 30 << 4*20.0 << 0.0
 +            << 25 << 4 << 1 << ListRange(0+4, 15+4);
 +    QTest::newRow("move from below view, move multiple up, move to top") << 30 << 0.0 << 0.0
 +            << 20 << 0 << 3 << ListRange(0, 15);
 +    QTest::newRow("move from below view, move multiple up, move to top, contentY not 0") << 30 << 4*20.0 << 0.0
 +            << 25 << 4 << 3 << ListRange(0+4, 15+4);
 +
 +    QTest::newRow("move from below view, move 1 up, move to bottom") << 30 << 0.0 << 0.0
 +            << 20 << 15 << 1 << ListRange(15, 15);
 +    QTest::newRow("move from below view, move 1 up, move to bottom, contentY not 0") << 30 << 4*20.0 << 0.0
 +            << 25 << 15+4 << 1 << ListRange(15+4, 15+4);
 +    QTest::newRow("move from below view, move multiple up, move to to bottom") << 30 << 0.0 << 0.0
 +            << 20 << 15 << 3 << ListRange(15, 15);
 +    QTest::newRow("move from below view, move multiple up, move to bottom, contentY not 0") << 30 << 4*20.0 << 0.0
 +            << 25 << 15+4 << 3 << ListRange(15+4, 15+4);
 +}
 +
 +void tst_QQuickListView::removeTransitions()
 +{
 +    QFETCH(int, initialItemCount);
 +    QFETCH(bool, shouldAnimateTargets);
 +    QFETCH(qreal, contentY);
 +    QFETCH(int, removalIndex);
 +    QFETCH(int, removalCount);
 +    QFETCH(ListRange, expectedDisplacedIndexes);
 +
 +    // added items should end here
 +    QPointF targetItems_transitionTo(-50, -50);
 +
 +    // displaced items should pass through this points
 +    QPointF displacedItems_transitionVia(100, 100);
 +
 +    QaimModel model;
 +    for (int i = 0; i < initialItemCount; i++)
 +        model.addItem("Original item" + QString::number(i), "");
 +    QaimModel model_targetItems_transitionTo;
 +    QaimModel model_displacedItems_transitionVia;
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("model_targetItems_transitionTo", &model_targetItems_transitionTo);
 +    ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
 +    ctxt->setContextProperty("targetItems_transitionTo", targetItems_transitionTo);
 +    ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
 +    ctxt->setContextProperty("testObject", testObject);
 +    canvas->setSource(testFileUrl("removeTransitions.qml"));
 +    canvas->show();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
 +    if (contentY != 0) {
 +        listview->setContentY(contentY);
 +        QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +    }
 +
 +    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
 +
 +    // only target items that are visible should be animated
 +    QList<QPair<QString, QString> > expectedTargetData;
 +    QList<int> targetIndexes;
 +    if (shouldAnimateTargets) {
 +        for (int i=removalIndex; i<removalIndex+removalCount; i++) {
 +            if (i >= contentY / 20 && i < (contentY + listview->height()) / 20) {
 +                expectedTargetData << qMakePair(model.name(i), model.number(i));
 +                targetIndexes << i;
 +            }
 +        }
 +        QVERIFY(expectedTargetData.count() > 0);
 +    }
 +
 +    // calculate targetItems and expectedTargets before model changes
 +    QList<QQuickItem *> targetItems = findItems<QQuickItem>(contentItem, "wrapper", targetIndexes);
 +    QVariantMap expectedTargets;
 +    for (int i=0; i<targetIndexes.count(); i++)
 +        expectedTargets[model.name(targetIndexes[i])] = targetIndexes[i];
 +
 +    // start animation
 +    model.removeItems(removalIndex, removalCount);
 +    QTRY_COMPARE(model.count(), listview->count());
 +
 +    if (shouldAnimateTargets) {
 +        QTRY_COMPARE(listview->property("targetTransitionsDone").toInt(), expectedTargetData.count());
 +        QTRY_COMPARE(listview->property("displaceTransitionsDone").toInt(),
 +                     expectedDisplacedIndexes.isValid() ? expectedDisplacedIndexes.count() : 0);
 +
 +        // check the target and displaced items were animated
 +        model_targetItems_transitionTo.matchAgainst(expectedTargetData, "wasn't animated to target 'to' pos", "shouldn't have been animated to target 'to' pos");
 +        model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim");
 +
 +        // check attached properties
 +        QCOMPARE(listview->property("targetTrans_items").toMap(), expectedTargets);
 +        matchIndexLists(listview->property("targetTrans_targetIndexes").toList(), targetIndexes);
 +        matchItemLists(listview->property("targetTrans_targetItems").toList(), targetItems);
 +        if (expectedDisplacedIndexes.isValid()) {
 +            // adjust expectedDisplacedIndexes to their final values after the move
 +            QList<int> displacedIndexes = adjustIndexesForRemoveDisplaced(expectedDisplacedIndexes.indexes, removalIndex, removalCount);
 +            matchItemsAndIndexes(listview->property("displacedTrans_items").toMap(), model, displacedIndexes);
 +            matchIndexLists(listview->property("displacedTrans_targetIndexes").toList(), targetIndexes);
 +            matchItemLists(listview->property("displacedTrans_targetItems").toList(), targetItems);
 +        }
 +    } else {
 +        QTRY_COMPARE(model_targetItems_transitionTo.count(), 0);
 +        QTRY_COMPARE(model_displacedItems_transitionVia.count(), 0);
 +    }
 +
 +    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
 +    int firstVisibleIndex = -1;
 +    int itemCount = items.count();
 +
 +    for (int i=0; i<items.count(); i++) {
 +        QQmlExpression e(qmlContext(items[i]), items[i], "index");
 +        int index = e.evaluate().toInt();
 +        if (firstVisibleIndex < 0 && items[i]->y() >= contentY)
 +            firstVisibleIndex = index;
 +        if (index < 0)
 +            itemCount--;    // exclude deleted items
 +    }
 +    QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +
 +    // verify all items moved to the correct final positions
 +    for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QCOMPARE(item->x(), 0.0);
 +        QCOMPARE(item->y(), contentY + (i-firstVisibleIndex) * 20.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::removeTransitions_data()
 +{
 +    QTest::addColumn<int>("initialItemCount");
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<bool>("shouldAnimateTargets");
 +    QTest::addColumn<int>("removalIndex");
 +    QTest::addColumn<int>("removalCount");
 +    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
 +
 +    // All items that are visible following the remove operation should be animated.
 +    // Remove targets that are outside of the view should not be animated.
 +
 +    QTest::newRow("remove 1 before start")
 +            << 30 << 20.0 * 3 << false
 +            << 2 << 1 << ListRange();
 +    QTest::newRow("remove multiple, all before start")
 +            << 30 << 20.0 * 3 << false
 +            << 0 << 3 << ListRange();
 +    QTest::newRow("remove mix of before and after start")
 +            << 30 << 20.0 * 3 << true
 +            << 2 << 3 << ListRange(5, 20);  // 5-20 are visible after the remove
 +
 +    QTest::newRow("remove 1 from start")
 +            << 30 << 0.0 << true
 +            << 0 << 1 << ListRange(1, 16);  // 1-16 are visible after the remove
 +    QTest::newRow("remove multiple from start")
 +            << 30 << 0.0 << true
 +            << 0 << 3 << ListRange(3, 18);  // 3-18 are visible after the remove
 +    QTest::newRow("remove 1 from start, content y not 0")
 +            << 30 << 20.0 * 2 << true  // first visible is index 2, so translate the displaced indexes by 2
 +            << 2 << 1 << ListRange(1 + 2, 16 + 2);
 +    QTest::newRow("remove multiple from start, content y not 0")
 +            << 30 << 20.0 * 2 << true    // first visible is index 2
 +            << 2 << 3 << ListRange(3 + 2, 18 + 2);
 +
 +    QTest::newRow("remove 1 from middle")
 +            << 30 << 0.0 << true
 +            << 5 << 1 << ListRange(6, 16);
 +    QTest::newRow("remove multiple from middle")
 +            << 30 << 0.0 << true
 +            << 5 << 3 << ListRange(8, 18);
 +
 +
 +    QTest::newRow("remove 1 from bottom")
 +            << 30 << 0.0 << true
 +            << 15 << 1 << ListRange(16, 16);
 +
 +    // remove 15, 16, 17
 +    // 15 will animate as the target item, 16 & 17 won't be animated since they are outside
 +    // the view, and 18 will be animated as the displaced item to replace the last item
 +    QTest::newRow("remove multiple from bottom")
 +            << 30 << 0.0 << true
 +            << 15 << 3 << ListRange(18, 18);
 +
 +    QTest::newRow("remove 1 from bottom, content y not 0")
 +            << 30 << 20.0 * 2 << true
 +            << 15 + 2 << 1 << ListRange(16 + 2, 16 + 2);
 +    QTest::newRow("remove multiple from bottom, content y not 0")
 +            << 30 << 20.0 * 2 << true
 +            << 15 + 2 << 3 << ListRange(18 + 2, 18 + 2);
 +
 +
 +    QTest::newRow("remove 1 after end")
 +            << 30 << 0.0 << false
 +            << 17 << 1 << ListRange();
 +    QTest::newRow("remove multiple after end")
 +            << 30 << 0.0 << false
 +            << 17 << 3 << ListRange();
 +}
 +
++void tst_QQuickListView::displacedTransitions()
++{
++    QFETCH(bool, useDisplaced);
++    QFETCH(bool, displacedEnabled);
++    QFETCH(bool, useAddDisplaced);
++    QFETCH(bool, addDisplacedEnabled);
++    QFETCH(bool, useMoveDisplaced);
++    QFETCH(bool, moveDisplacedEnabled);
++    QFETCH(bool, useRemoveDisplaced);
++    QFETCH(bool, removeDisplacedEnabled);
++    QFETCH(ListChange, change);
++    QFETCH(ListRange, expectedDisplacedIndexes);
++
++    QaimModel model;
++    for (int i = 0; i < 30; i++)
++        model.addItem("Original item" + QString::number(i), "");
++    QaimModel model_displaced_transitionVia;
++    QaimModel model_addDisplaced_transitionVia;
++    QaimModel model_moveDisplaced_transitionVia;
++    QaimModel model_removeDisplaced_transitionVia;
++
++    QPointF displaced_transitionVia(-50, -100);
++    QPointF addDisplaced_transitionVia(-150, 100);
++    QPointF moveDisplaced_transitionVia(50, -100);
++    QPointF removeDisplaced_transitionVia(150, 100);
++
++    QQuickView *canvas = createView();
++    QQmlContext *ctxt = canvas->rootContext();
++    TestObject *testObject = new TestObject(canvas);
++    ctxt->setContextProperty("testModel", &model);
++    ctxt->setContextProperty("testObject", testObject);
++    ctxt->setContextProperty("model_displaced_transitionVia", &model_displaced_transitionVia);
++    ctxt->setContextProperty("model_addDisplaced_transitionVia", &model_addDisplaced_transitionVia);
++    ctxt->setContextProperty("model_moveDisplaced_transitionVia", &model_moveDisplaced_transitionVia);
++    ctxt->setContextProperty("model_removeDisplaced_transitionVia", &model_removeDisplaced_transitionVia);
++    ctxt->setContextProperty("displaced_transitionVia", displaced_transitionVia);
++    ctxt->setContextProperty("addDisplaced_transitionVia", addDisplaced_transitionVia);
++    ctxt->setContextProperty("moveDisplaced_transitionVia", moveDisplaced_transitionVia);
++    ctxt->setContextProperty("removeDisplaced_transitionVia", removeDisplaced_transitionVia);
++    ctxt->setContextProperty("useDisplaced", useDisplaced);
++    ctxt->setContextProperty("displacedEnabled", displacedEnabled);
++    ctxt->setContextProperty("useAddDisplaced", useAddDisplaced);
++    ctxt->setContextProperty("addDisplacedEnabled", addDisplacedEnabled);
++    ctxt->setContextProperty("useMoveDisplaced", useMoveDisplaced);
++    ctxt->setContextProperty("moveDisplacedEnabled", moveDisplacedEnabled);
++    ctxt->setContextProperty("useRemoveDisplaced", useRemoveDisplaced);
++    ctxt->setContextProperty("removeDisplacedEnabled", removeDisplacedEnabled);
++    canvas->setSource(testFileUrl("displacedTransitions.qml"));
++    canvas->show();
++    qApp->processEvents();
++
++    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
++    QTRY_VERIFY(listview != 0);
++    QQuickItem *contentItem = listview->contentItem();
++    QVERIFY(contentItem != 0);
++    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
++
++    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
++    listview->setProperty("displaceTransitionsDone", false);
++
++    switch (change.type) {
++        case ListChange::Inserted:
++        {
++            QList<QPair<QString, QString> > targetItemData;
++            for (int i=change.index; i<change.index + change.count; ++i)
++                targetItemData << qMakePair(QString("new item %1").arg(i), QString::number(i));
++            model.insertItems(change.index, targetItemData);
++            QTRY_COMPARE(model.count(), listview->count());
++            break;
++        }
++        case ListChange::Removed:
++            model.removeItems(change.index, change.count);
++            QTRY_COMPARE(model.count(), listview->count());
++            break;
++        case ListChange::Moved:
++            model.moveItems(change.index, change.to, change.count);
++            QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
++            break;
++        case ListChange::SetCurrent:
++        case ListChange::SetContentY:
++            break;
++    }
++    if ((useDisplaced && displacedEnabled)
++            || (useAddDisplaced && addDisplacedEnabled)
++            || (useMoveDisplaced && moveDisplacedEnabled)
++            || (useRemoveDisplaced && removeDisplacedEnabled)) {
++        QTRY_VERIFY(listview->property("displaceTransitionsDone").toBool());
++    }
++
++    if (change.type == ListChange::Inserted && useAddDisplaced && addDisplacedEnabled)
++        model_addDisplaced_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with add displaced", "shouldn't have been animated with add displaced");
++    else
++        QCOMPARE(model_addDisplaced_transitionVia.count(), 0);
++    if (change.type == ListChange::Moved && useMoveDisplaced && moveDisplacedEnabled)
++        model_moveDisplaced_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with move displaced", "shouldn't have been animated with move displaced");
++    else
++        QCOMPARE(model_moveDisplaced_transitionVia.count(), 0);
++    if (change.type == ListChange::Removed && useRemoveDisplaced && removeDisplacedEnabled)
++        model_removeDisplaced_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with remove displaced", "shouldn't have been animated with remove displaced");
++    else
++        QCOMPARE(model_removeDisplaced_transitionVia.count(), 0);
++
++    if (useDisplaced && displacedEnabled
++            && ( (change.type == ListChange::Inserted && (!useAddDisplaced || !addDisplacedEnabled))
++                 || (change.type == ListChange::Moved && (!useMoveDisplaced || !moveDisplacedEnabled))
++                 || (change.type == ListChange::Removed && (!useRemoveDisplaced || !removeDisplacedEnabled))) ) {
++        model_displaced_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with generic displaced", "shouldn't have been animated with generic displaced");
++    } else {
++        QCOMPARE(model_displaced_transitionVia.count(), 0);
++    }
++
++    // verify all items moved to the correct final positions
++    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
++    for (int i=0; i < model.count() && i < items.count(); ++i) {
++        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
++        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
++        QCOMPARE(item->x(), 0.0);
++        QCOMPARE(item->y(), i * 20.0);
++        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
++        QVERIFY(name != 0);
++        QTRY_COMPARE(name->text(), model.name(i));
++    }
++
++    delete canvas;
++}
++
++void tst_QQuickListView::displacedTransitions_data()
++{
++    QTest::addColumn<bool>("useDisplaced");
++    QTest::addColumn<bool>("displacedEnabled");
++    QTest::addColumn<bool>("useAddDisplaced");
++    QTest::addColumn<bool>("addDisplacedEnabled");
++    QTest::addColumn<bool>("useMoveDisplaced");
++    QTest::addColumn<bool>("moveDisplacedEnabled");
++    QTest::addColumn<bool>("useRemoveDisplaced");
++    QTest::addColumn<bool>("removeDisplacedEnabled");
++    QTest::addColumn<ListChange>("change");
++    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
++
++    QTest::newRow("no displaced transitions at all")
++            << false << false
++            << false << false
++            << false << false
++            << false << false
++            << ListChange::insert(0, 1) << ListRange(0, 15);
++
++    QTest::newRow("just displaced")
++            << true << true
++            << false << false
++            << false << false
++            << false << false
++            << ListChange::insert(0, 1) << ListRange(0, 15);
++
++    QTest::newRow("just displaced (not enabled)")
++            << true << false
++            << false << false
++            << false << false
++            << false << false
++            << ListChange::insert(0, 1) << ListRange(0, 15);
++
++    QTest::newRow("displaced + addDisplaced")
++            << true << true
++            << true << true
++            << false << false
++            << false << false
++            << ListChange::insert(0, 1) << ListRange(0, 15);
++
++    QTest::newRow("displaced + addDisplaced (not enabled)")
++            << true << true
++            << true << false
++            << false << false
++            << false << false
++            << ListChange::insert(0, 1) << ListRange(0, 15);
++
++    QTest::newRow("displaced + moveDisplaced")
++            << true << true
++            << false << false
++            << true << true
++            << false << false
++            << ListChange::move(0, 10, 1) << ListRange(1, 10);
++
++    QTest::newRow("displaced + moveDisplaced (not enabled)")
++            << true << true
++            << false << false
++            << true << false
++            << false << false
++            << ListChange::move(0, 10, 1) << ListRange(1, 10);
++
++    QTest::newRow("displaced + removeDisplaced")
++            << true << true
++            << false << false
++            << false << false
++            << true << true
++            << ListChange::remove(0, 1) << ListRange(1, 16);
++
++    QTest::newRow("displaced + removeDisplaced (not enabled)")
++            << true << true
++            << false << false
++            << false << false
++            << true << false
++            << ListChange::remove(0, 1) << ListRange(1, 16);
++
++
++    QTest::newRow("displaced + add, should use generic displaced for a remove")
++            << true << true
++            << true << true
++            << false << false
++            << true << false
++            << ListChange::remove(0, 1) << ListRange(1, 16);
++}
++
 +void tst_QQuickListView::multipleTransitions()
 +{
++    QSKIP("QTBUG-24523");
++
 +    // Tests that if you interrupt a transition in progress with another action that
 +    // cancels the previous transition, the resulting items are still placed correctly.
 +
 +    QFETCH(int, initialCount);
 +    QFETCH(qreal, contentY);
 +    QFETCH(QList<ListChange>, changes);
++    QFETCH(bool, rippleAddDisplaced);
 +
-     QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
-     int firstVisibleIndex = -1;
-     for (int i=0; i<items.count(); i++) {
-         if (items[i]->y() >= contentY) {
-             QQmlExpression e(qmlContext(items[i]), items[i], "index");
-             firstVisibleIndex = e.evaluate().toInt();
-             break;
-         }
-     }
-     QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
 +    QPointF addTargets_transitionFrom(-50, -50);
 +    QPointF addDisplaced_transitionFrom(-50, 50);
 +    QPointF moveTargets_transitionFrom(50, -50);
 +    QPointF moveDisplaced_transitionFrom(50, 50);
++    QPointF removeTargets_transitionTo(-100, 300);
++    QPointF removeDisplaced_transitionFrom(100, 300);
 +
 +    QmlListModel model;
 +    for (int i = 0; i < initialCount; i++)
 +        model.addItem("Original item" + QString::number(i), "");
 +
 +    QQuickView *canvas = createView();
 +    QQmlContext *ctxt = canvas->rootContext();
 +    TestObject *testObject = new TestObject;
 +    ctxt->setContextProperty("testModel", &model);
 +    ctxt->setContextProperty("testObject", testObject);
 +    ctxt->setContextProperty("addTargets_transitionFrom", addTargets_transitionFrom);
 +    ctxt->setContextProperty("addDisplaced_transitionFrom", addDisplaced_transitionFrom);
 +    ctxt->setContextProperty("moveTargets_transitionFrom", moveTargets_transitionFrom);
 +    ctxt->setContextProperty("moveDisplaced_transitionFrom", moveDisplaced_transitionFrom);
++    ctxt->setContextProperty("removeTargets_transitionTo", removeTargets_transitionTo);
++    ctxt->setContextProperty("removeDisplaced_transitionFrom", removeDisplaced_transitionFrom);
++    ctxt->setContextProperty("rippleAddDisplaced", rippleAddDisplaced);
 +    canvas->setSource(testFileUrl("multipleTransitions.qml"));
 +    canvas->show();
++    QTest::qWaitForWindowShown(canvas);
 +
 +    QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
 +    QTRY_VERIFY(listview != 0);
 +    QQuickItem *contentItem = listview->contentItem();
 +    QVERIFY(contentItem != 0);
 +    QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +
++    if (contentY != 0) {
++        listview->setContentY(contentY);
++        QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
++    }
++
 +    int timeBetweenActions = canvas->rootObject()->property("timeBetweenActions").toInt();
 +
 +    QList<QPair<QString, QString> > targetItems;
 +    for (int i=0; i<changes.count(); i++) {
 +        switch (changes[i].type) {
 +            case ListChange::Inserted:
 +            {
 +                for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
 +                    targetItems << qMakePair(QString("new item %1").arg(j), QString::number(j));
 +                model.insertItems(changes[i].index, targetItems);
 +                QTRY_COMPARE(model.count(), listview->count());
 +                QTRY_VERIFY(listview->property("runningAddTargets").toBool());
 +                QTRY_VERIFY(listview->property("runningAddDisplaced").toBool());
 +                if (i == changes.count() - 1) {
 +                    QTRY_VERIFY(!listview->property("runningAddTargets").toBool());
 +                    QTRY_VERIFY(!listview->property("runningAddDisplaced").toBool());
 +                } else {
 +                    QTest::qWait(timeBetweenActions);
 +                }
 +                break;
 +            }
 +            case ListChange::Removed:
 +                for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
 +                    targetItems << qMakePair(model.name(i), model.number(i));
 +                model.removeItems(changes[i].index, changes[i].count);
 +                QTRY_COMPARE(model.count(), listview->count());
 +                QTRY_VERIFY(listview->property("runningRemoveTargets").toBool());
 +                QTRY_VERIFY(listview->property("runningRemoveDisplaced").toBool());
 +                if (i == changes.count() - 1) {
 +                    QTRY_VERIFY(!listview->property("runningRemoveTargets").toBool());
 +                    QTRY_VERIFY(!listview->property("runningRemoveDisplaced").toBool());
 +                } else {
 +                    QTest::qWait(timeBetweenActions);
 +                }
 +                break;
 +            case ListChange::Moved:
 +                for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
 +                    targetItems << qMakePair(model.name(i), model.number(i));
 +                model.moveItems(changes[i].index, changes[i].to, changes[i].count);
 +                QTRY_VERIFY(listview->property("runningMoveTargets").toBool());
 +                QTRY_VERIFY(listview->property("runningMoveDisplaced").toBool());
 +                if (i == changes.count() - 1) {
 +                    QTRY_VERIFY(!listview->property("runningMoveTargets").toBool());
 +                    QTRY_VERIFY(!listview->property("runningMoveDisplaced").toBool());
 +                } else {
 +                    QTest::qWait(timeBetweenActions);
 +                }
 +                break;
 +            case ListChange::SetCurrent:
 +                listview->setCurrentIndex(changes[i].index);
 +                break;
 +            case ListChange::SetContentY:
 +                listview->setContentY(changes[i].pos);
 +                QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
 +                break;
 +        }
 +    }
 +    QCOMPARE(listview->count(), model.count());
 +
-     int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
-     for (int i=firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
 +    // verify all items moved to the correct final positions
-             );
++    QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
++    for (int i=0; i < model.count() && i < items.count(); ++i) {
 +        QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
 +        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
 +        QTRY_COMPARE(item->x(), 0.0);
 +        QTRY_COMPARE(item->y(), i*20.0);
 +        QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
 +        QVERIFY(name != 0);
 +        QTRY_COMPARE(name->text(), model.name(i));
 +    }
 +
 +    delete canvas;
 +    delete testObject;
 +}
 +
 +void tst_QQuickListView::multipleTransitions_data()
 +{
 +    QTest::addColumn<int>("initialCount");
 +    QTest::addColumn<qreal>("contentY");
 +    QTest::addColumn<QList<ListChange> >("changes");
++    QTest::addColumn<bool>("rippleAddDisplaced");
 +
 +    // the added item and displaced items should move to final dest correctly
 +    QTest::newRow("add item, then move it immediately") << 10 << 0.0 << (QList<ListChange>()
 +            << ListChange::insert(0, 1)
 +            << ListChange::move(0, 3, 1)
-             );
++            )
++            << false;
 +
 +    // items affected by the add should change from move to add transition
 +    QTest::newRow("move, then insert item before the moved item") << 20 << 0.0 << (QList<ListChange>()
 +            << ListChange::move(1, 10, 3)
 +            << ListChange::insert(0, 1)
-             );
++            )
++            << false;
 +
 +    // items should be placed correctly if you trigger a transition then refill for that index
 +    QTest::newRow("add at 0, flick down, flick back to top and add at 0 again") << 20 << 0.0 << (QList<ListChange>()
 +            << ListChange::insert(0, 1)
 +            << ListChange::setContentY(80.0)
 +            << ListChange::setContentY(0.0)
 +            << ListChange::insert(0, 1)
++            )
++            << false;
++
++    QTest::newRow("insert then remove same index, with ripple effect on add displaced") << 20 << 0.0 << (QList<ListChange>()
++            << ListChange::insert(1, 1)
++            << ListChange::remove(1, 1)
++            )
++            << true;
 +}
 +
 +QList<int> tst_QQuickListView::toIntList(const QVariantList &list)
 +{
 +    QList<int> ret;
 +    bool ok = true;
 +    for (int i=0; i<list.count(); i++) {
 +        ret << list[i].toInt(&ok);
 +        if (!ok)
 +            qWarning() << "tst_QQuickListView::toIntList(): not a number:" << list[i];
 +    }
 +
 +    return ret;
 +}
 +
 +void tst_QQuickListView::matchIndexLists(const QVariantList &indexLists, const QList<int> &expectedIndexes)
 +{
 +    for (int i=0; i<indexLists.count(); i++) {
 +        QSet<int> current = indexLists[i].value<QList<int> >().toSet();
 +        if (current != expectedIndexes.toSet())
 +            qDebug() << "Cannot match actual targets" << current << "with expected" << expectedIndexes;
 +        QCOMPARE(current, expectedIndexes.toSet());
 +    }
 +}
 +
 +void tst_QQuickListView::matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList<int> &expectedIndexes)
 +{
 +    for (QVariantMap::const_iterator it = items.begin(); it != items.end(); ++it) {
 +        QVERIFY(it.value().type() == QVariant::Int);
 +        QString name = it.key();
 +        int itemIndex = it.value().toInt();
 +        QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex)));
 +        if (model.name(itemIndex) != name)
 +            qDebug() << itemIndex;
 +        QCOMPARE(model.name(itemIndex), name);
 +    }
 +    QCOMPARE(items.count(), expectedIndexes.count());
 +}
 +
 +void tst_QQuickListView::matchItemLists(const QVariantList &itemLists, const QList<QQuickItem *> &expectedItems)
 +{
 +    for (int i=0; i<itemLists.count(); i++) {
 +        QVERIFY(itemLists[i].type() == QVariant::List);
 +        QVariantList current = itemLists[i].toList();
 +        for (int j=0; j<current.count(); j++) {
 +            QQuickItem *o = qobject_cast<QQuickItem*>(current[j].value<QObject*>());
 +            QVERIFY2(o, QTest::toString(QString("Invalid actual item at %1").arg(j)));
 +            QVERIFY2(expectedItems.contains(o), QTest::toString(QString("Cannot match item %1").arg(j)));
 +        }
 +        QCOMPARE(current.count(), expectedItems.count());
 +    }
 +}
 +
 +
 +QTEST_MAIN(tst_QQuickListView)
 +
 +#include "tst_qquicklistview.moc"
 +
index 0000000,0000000..54f5705
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,196 @@@
++import QtQuick 2.0
++
++Rectangle {
++    id: root
++    width: 500
++    height: 500
++
++    property int duration: 50
++
++    property int targetTransitionsDone
++    property int displaceTransitionsDone
++
++    property var targetTrans_items: new Object()
++    property var targetTrans_targetIndexes: new Array()
++    property var targetTrans_targetItems: new Array()
++
++    property var displacedTrans_items: new Object()
++    property var displacedTrans_targetIndexes: new Array()
++    property var displacedTrans_targetItems: new Array()
++
++    // for QQmlListProperty types
++    function copyList(propList) {
++        var temp = new Array()
++        for (var i=0; i<propList.length; i++)
++            temp.push(propList[i])
++        return temp
++    }
++
++    function checkPos(x, y, name) {
++        if (Qt.point(x, y) == targetItems_transitionFrom)
++            model_targetItems_transitionFrom.addItem(name, "")
++        if (Qt.point(x, y) == displacedItems_transitionVia)
++            model_displacedItems_transitionVia.addItem(name, "")
++    }
++
++    Transition {
++        id: targetTransition
++        enabled: enableAddTransition
++
++        SequentialAnimation {
++            ScriptAction {
++                script: {
++                    root.targetTrans_items[targetTransition.ViewTransition.item.nameData] = targetTransition.ViewTransition.index
++                    root.targetTrans_targetIndexes.push(targetTransition.ViewTransition.targetIndexes)
++                    root.targetTrans_targetItems.push(root.copyList(targetTransition.ViewTransition.targetItems))
++                }
++            }
++            ParallelAnimation {
++                NumberAnimation { properties: "x"; from: targetItems_transitionFrom.x; duration: root.duration }
++                NumberAnimation { properties: "y"; from: targetItems_transitionFrom.y; duration: root.duration }
++            }
++
++            ScriptAction { script: root.targetTransitionsDone += 1 }
++        }
++    }
++
++    Transition {
++        id: displaced
++
++        SequentialAnimation {
++            ScriptAction {
++                script: {
++                    root.displacedTrans_items[displaced.ViewTransition.item.nameData] = displaced.ViewTransition.index
++                    root.displacedTrans_targetIndexes.push(displaced.ViewTransition.targetIndexes)
++                    root.displacedTrans_targetItems.push(root.copyList(displaced.ViewTransition.targetItems))
++                }
++            }
++            ParallelAnimation {
++                NumberAnimation { properties: "x"; duration: root.duration; to: displacedItems_transitionVia.x }
++                NumberAnimation { properties: "y"; duration: root.duration; to: displacedItems_transitionVia.y }
++            }
++            NumberAnimation { properties: "x,y"; duration: root.duration }
++
++            ScriptAction { script: root.displaceTransitionsDone += 1 }
++        }
++
++    }
++
++    Row {
++        objectName: "row"
++
++        property int count: children.length - 1 // omit Repeater
++
++        x: 50; y: 50
++        width: 400; height: 400
++        Repeater {
++            objectName: "repeater"
++            Rectangle {
++                property string nameData: name
++                objectName: "wrapper"
++                width: 30 + index*5
++                height: 30 + index*5
++                border.width: 1
++                Column {
++                    Text { text: index }
++                    Text { objectName: "name"; text: name }
++                    Text { text: parent.parent.y }
++                }
++                onXChanged: root.checkPos(x, y, name)
++                onYChanged: root.checkPos(x, y, name)
++            }
++        }
++
++        add: targetTransition
++        move: displaced
++    }
++
++    Column {
++        objectName: "column"
++
++        property int count: children.length - 1 // omit Repeater
++
++        x: 50; y: 50
++        width: 400; height: 400
++        Repeater {
++            objectName: "repeater"
++            Rectangle {
++                property string nameData: name
++                objectName: "wrapper"
++                width: 30 + index*5
++                height: 30 + index*5
++                border.width: 1
++                Column {
++                    Text { text: index }
++                    Text { objectName: "name"; text: name }
++                    Text { text: parent.parent.y }
++                }
++                onXChanged: root.checkPos(x, y, name)
++                onYChanged: root.checkPos(x, y, name)
++            }
++        }
++
++        add: targetTransition
++        move: displaced
++    }
++
++    Grid {
++        objectName: "grid"
++
++        property int count: children.length - 1 // omit Repeater
++
++        x: 50; y: 50
++        width: 400; height: 400
++        Repeater {
++            objectName: "repeater"
++            Rectangle {
++                property string nameData: name
++                objectName: "wrapper"
++                width: 30 + index*5
++                height: 30 + index*5
++                border.width: 1
++                Column {
++                    Text { text: index }
++                    Text { objectName: "name"; text: name }
++                    Text { text: parent.parent.y }
++                }
++
++                onXChanged: root.checkPos(x, y, name)
++                onYChanged: root.checkPos(x, y, name)
++            }
++        }
++
++        add: targetTransition
++        move: displaced
++    }
++
++    Flow {
++        objectName: "flow"
++
++        property int count: children.length - 1 // omit Repeater
++
++        x: 50; y: 50
++        width: 400; height: 400
++        Repeater {
++            objectName: "repeater"
++            Rectangle {
++                property string nameData: name
++                objectName: "wrapper"
++                width: 30 + index*5
++                height: 30 + index*5
++                border.width: 1
++                Column {
++                    Text { text: index }
++                    Text { objectName: "name"; text: name }
++                    Text { text: parent.parent.x + " " + parent.parent.y }
++                }
++                onXChanged: root.checkPos(x, y, name)
++                onYChanged: root.checkPos(x, y, name)
++            }
++        }
++
++        add: targetTransition
++        move: displaced
++    }
++}
++
index 56fe465,0000000..5633796
mode 100644,000000..100644
--- /dev/null
@@@ -1,14 -1,0 +1,15 @@@
 +CONFIG += testcase
 +TARGET = tst_qquickpositioners
 +SOURCES += tst_qquickpositioners.cpp
 +
++include (../shared/util.pri)
 +include (../../shared/util.pri)
 +
 +macx:CONFIG -= app_bundle
 +
 +testDataFiles.files = data
 +testDataFiles.path = .
 +DEPLOYMENT += testDataFiles
 +
 +CONFIG += parallel_test
 +QT += core-private gui-private v8-private qml-private quick-private opengl-private testlib
index ecc4c80,0000000..8f517a4
mode 100644,000000..100644
--- /dev/null
@@@ -1,1472 -1,0 +1,1927 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <QtTest/QtTest>
 +#include <private/qlistmodelinterface_p.h>
 +#include <QtQuick/qquickview.h>
 +#include <qqmlengine.h>
 +#include <QtQuick/private/qquickrectangle_p.h>
 +#include <QtQuick/private/qquickpositioners_p.h>
 +#include <QtQuick/private/qquicktransition_p.h>
 +#include <private/qquickitem_p.h>
 +#include <qqmlexpression.h>
++#include "../shared/viewtestutil.h"
++#include "../shared/visualtestutil.h"
 +#include "../../shared/util.h"
 +
++using namespace QQuickViewTestUtil;
++using namespace QQuickVisualTestUtil;
++
 +class tst_qquickpositioners : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_qquickpositioners();
 +
 +private slots:
 +    void test_horizontal();
 +    void test_horizontal_rtl();
 +    void test_horizontal_spacing();
 +    void test_horizontal_spacing_rightToLeft();
 +    void test_horizontal_animated();
 +    void test_horizontal_animated_rightToLeft();
 +    void test_horizontal_animated_disabled();
 +    void test_vertical();
 +    void test_vertical_spacing();
 +    void test_vertical_animated();
 +    void test_grid();
 +    void test_grid_topToBottom();
 +    void test_grid_rightToLeft();
 +    void test_grid_spacing();
 +    void test_grid_row_column_spacing();
 +    void test_grid_animated();
 +    void test_grid_animated_rightToLeft();
 +    void test_grid_zero_columns();
 +    void test_propertychanges();
 +    void test_repeater();
 +    void test_flow();
 +    void test_flow_rightToLeft();
 +    void test_flow_topToBottom();
 +    void test_flow_resize();
 +    void test_flow_resize_rightToLeft();
 +    void test_flow_implicit_resize();
 +    void test_conflictinganchors();
 +    void test_mirroring();
 +    void test_allInvisible();
 +    void test_attachedproperties();
 +    void test_attachedproperties_data();
 +    void test_attachedproperties_dynamic();
++    void addTransitions_row();
++    void addTransitions_row_data();
++    void addTransitions_column();
++    void addTransitions_column_data();
++    void addTransitions_grid();
++    void addTransitions_grid_data();
++    void addTransitions_flow();
++    void addTransitions_flow_data();
++    void moveTransitions_row();
++    void moveTransitions_row_data();
++    void moveTransitions_column();
++    void moveTransitions_column_data();
++    void moveTransitions_grid();
++    void moveTransitions_grid_data();
++    void moveTransitions_flow();
++    void moveTransitions_flow_data();
 +
 +private:
 +    QQuickView *createView(const QString &filename, bool wait=true);
++
++    void addTransitions(const QString &positionerObjectName);
++    void addTransitions_data();
++    void moveTransitions(const QString &positionerObjectName);
++    void moveTransitions_data();
++    void matchIndexLists(const QVariantList &indexLists, const QList<int> &expectedIndexes);
++    void matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList<int> &expectedIndexes);
++    void matchItemLists(const QVariantList &itemLists, const QList<QQuickItem *> &expectedItems);
++    void checkItemPositions(QQuickItem *positioner, QaimModel *model, qreal incrementalSize);
 +};
 +
++void tst_qquickpositioners::addTransitions_row()
++{
++    addTransitions("row");
++}
++
++void tst_qquickpositioners::addTransitions_row_data()
++{
++    addTransitions_data();
++}
++
++void tst_qquickpositioners::addTransitions_column()
++{
++    addTransitions("column");
++}
++
++void tst_qquickpositioners::addTransitions_column_data()
++{
++    addTransitions_data();
++}
++
++void tst_qquickpositioners::addTransitions_grid()
++{
++    addTransitions("grid");
++}
++
++void tst_qquickpositioners::addTransitions_grid_data()
++{
++    // don't use addTransitions_data() because grid displaces items differently
++    // (adding items further down the grid can cause displace transitions at
++    // previous indexes, since grid is auto-resized to tightly fit all of its items)
++
++    QTest::addColumn<int>("initialItemCount");
++    QTest::addColumn<int>("insertionIndex");
++    QTest::addColumn<int>("insertionCount");
++    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
++
++    QTest::newRow("add one @ start") << 10 << 0 << 1 << ListRange(0, 9);
++    QTest::newRow("add one @ middle") << 10 << 5 << 1 << ListRange(3, 3) + ListRange(5, 9);
++    QTest::newRow("add one @ end") << 10 << 10 << 1 << ListRange(3, 3) + ListRange(7, 7);
++
++    QTest::newRow("add multiple @ start") << 10 << 0 << 3 << ListRange(0, 9);
++    QTest::newRow("add multiple @ middle") << 10 << 5 << 3 << ListRange(1, 3) + ListRange(5, 9);
++    QTest::newRow("add multiple @ end") << 10 << 10 << 3 << ListRange(1, 3) + ListRange(5, 7) + ListRange(9, 9);
++}
++
++void tst_qquickpositioners::addTransitions_flow()
++{
++    addTransitions("flow");
++}
++
++void tst_qquickpositioners::addTransitions_flow_data()
++{
++    addTransitions_data();
++}
++
++void tst_qquickpositioners::moveTransitions_row()
++{
++    moveTransitions("row");
++}
++
++void tst_qquickpositioners::moveTransitions_row_data()
++{
++    moveTransitions_data();
++}
++
++void tst_qquickpositioners::moveTransitions_column()
++{
++    moveTransitions("column");
++}
++
++void tst_qquickpositioners::moveTransitions_column_data()
++{
++    moveTransitions_data();
++}
++
++void tst_qquickpositioners::moveTransitions_grid()
++{
++    moveTransitions("grid");
++}
++
++void tst_qquickpositioners::moveTransitions_grid_data()
++{
++    // don't use moveTransitions_data() because grid displaces items differently
++    // (removing items further down the grid can cause displace transitions at
++    // previous indexes, since grid is auto-resized to tightly fit all of its items)
++
++    QTest::addColumn<int>("initialItemCount");
++    QTest::addColumn<ListChange>("change");
++    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
++
++    QTest::newRow("remove one @ start") << 10 << ListChange::remove(0, 1) << ListRange(1, 9);
++    QTest::newRow("remove one @ middle") << 10 << ListChange::remove(4, 1) << ListRange(2, 3) + ListRange(5, 9);
++    QTest::newRow("remove one @ end") << 10 << ListChange::remove(9, 1) << ListRange(2, 3) + ListRange(6, 7);
++
++    QTest::newRow("remove multiple @ start") << 10 << ListChange::remove(0, 3) << ListRange(3, 9);
++    QTest::newRow("remove multiple @ middle") << 10 << ListChange::remove(4, 3) << ListRange(1, 3) + ListRange(7, 9);
++    QTest::newRow("remove multiple @ end") << 10 << ListChange::remove(7, 3) << ListRange(1, 3) + ListRange(5, 6);
++}
++
++void tst_qquickpositioners::moveTransitions_flow()
++{
++    moveTransitions("flow");
++}
++
++void tst_qquickpositioners::moveTransitions_flow_data()
++{
++    moveTransitions_data();
++}
++
 +tst_qquickpositioners::tst_qquickpositioners()
 +{
 +}
 +
 +void tst_qquickpositioners::test_horizontal()
 +{
 +    QQuickView *canvas = createView(testFile("horizontal.qml"));
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", false);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 50.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 70.0);
 +    QCOMPARE(three->y(), 0.0);
 +
 +    QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
 +    QCOMPARE(row->width(), 110.0);
 +    QCOMPARE(row->height(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_horizontal_rtl()
 +{
 +    QQuickView *canvas = createView(testFile("horizontal.qml"));
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", true);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +
 +    QCOMPARE(one->x(), 60.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 40.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 0.0);
 +    QCOMPARE(three->y(), 0.0);
 +
 +    QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
 +    QCOMPARE(row->width(), 110.0);
 +    QCOMPARE(row->height(), 50.0);
 +
 +    // Change the width of the row and check that items stay to the right
 +    row->setWidth(200);
 +    QTRY_COMPARE(one->x(), 150.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 130.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 90.0);
 +    QCOMPARE(three->y(), 0.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_horizontal_spacing()
 +{
 +    QQuickView *canvas = createView(testFile("horizontal-spacing.qml"));
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", false);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 60.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 90.0);
 +    QCOMPARE(three->y(), 0.0);
 +
 +    QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
 +    QCOMPARE(row->width(), 130.0);
 +    QCOMPARE(row->height(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_horizontal_spacing_rightToLeft()
 +{
 +    QQuickView *canvas = createView(testFile("horizontal-spacing.qml"));
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", true);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +
 +    QCOMPARE(one->x(), 80.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 50.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 00.0);
 +    QCOMPARE(three->y(), 0.0);
 +
 +    QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
 +    QCOMPARE(row->width(), 130.0);
 +    QCOMPARE(row->height(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_horizontal_animated()
 +{
 +    QQuickView *canvas = createView(testFile("horizontal-animated.qml"), false);
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", false);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +
 +    //Note that they animate in
 +    QCOMPARE(one->x(), -100.0);
 +    QCOMPARE(two->x(), -100.0);
 +    QCOMPARE(three->x(), -100.0);
 +
 +    QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
 +
 +    QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
 +    QVERIFY(row);
 +    QCOMPARE(row->width(), 100.0);
 +    QCOMPARE(row->height(), 50.0);
 +
 +    //QTRY_COMPARE used instead of waiting for the expected time of animation completion
 +    //Note that this means the duration of the animation is NOT tested
 +
 +    QTRY_COMPARE(one->x(), 0.0);
 +    QTRY_COMPARE(one->y(), 0.0);
 +    QTRY_COMPARE(two->isVisible(), false);
 +    QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet
 +    QTRY_COMPARE(two->y(), 0.0);
 +    QTRY_COMPARE(three->x(), 50.0);
 +    QTRY_COMPARE(three->y(), 0.0);
 +
 +    //Add 'two'
 +    two->setVisible(true);
 +    QTRY_COMPARE(two->isVisible(), true);
 +    QTRY_COMPARE(row->width(), 150.0);
 +    QTRY_COMPARE(row->height(), 50.0);
 +
 +    QTest::qWait(0);//Let the animation start
 +    QVERIFY(two->x() >= -100.0 && two->x() < 50.0);
 +    QVERIFY(three->x() >= 50.0 && three->x() < 100.0);
 +
 +    QTRY_COMPARE(two->x(), 50.0);
 +    QTRY_COMPARE(three->x(), 100.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_horizontal_animated_rightToLeft()
 +{
 +    QQuickView *canvas = createView(testFile("horizontal-animated.qml"), false);
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", true);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +
 +    //Note that they animate in
 +    QCOMPARE(one->x(), -100.0);
 +    QCOMPARE(two->x(), -100.0);
 +    QCOMPARE(three->x(), -100.0);
 +
 +    QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
 +
 +    QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
 +    QVERIFY(row);
 +    QCOMPARE(row->width(), 100.0);
 +    QCOMPARE(row->height(), 50.0);
 +
 +    //QTRY_COMPARE used instead of waiting for the expected time of animation completion
 +    //Note that this means the duration of the animation is NOT tested
 +
 +    QTRY_COMPARE(one->x(), 50.0);
 +    QTRY_COMPARE(one->y(), 0.0);
 +    QTRY_COMPARE(two->isVisible(), false);
 +    QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet
 +    QTRY_COMPARE(two->y(), 0.0);
 +    QTRY_COMPARE(three->x(), 0.0);
 +    QTRY_COMPARE(three->y(), 0.0);
 +
 +    //Add 'two'
 +    two->setVisible(true);
 +    QTRY_COMPARE(two->isVisible(), true);
 +
 +    // New size should propagate after visible change
 +    QTRY_COMPARE(row->width(), 150.0);
 +    QTRY_COMPARE(row->height(), 50.0);
 +
 +    QTest::qWait(0);//Let the animation start
 +    QVERIFY(one->x() >= 50.0 && one->x() < 100);
 +    QVERIFY(two->x() >= -100.0 && two->x() < 50.0);
 +
 +    QTRY_COMPARE(one->x(), 100.0);
 +    QTRY_COMPARE(two->x(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_horizontal_animated_disabled()
 +{
 +    QQuickView *canvas = createView(testFile("horizontal-animated-disabled.qml"));
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +
 +    QQuickItem *row = canvas->rootObject()->findChild<QQuickItem*>("row");
 +    QVERIFY(row);
 +
 +    qApp->processEvents();
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->isVisible(), false);
 +    QCOMPARE(two->x(), -100.0);//Not 'in' yet
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 50.0);
 +    QCOMPARE(three->y(), 0.0);
 +
 +    //Add 'two'
 +    two->setVisible(true);
 +    QCOMPARE(two->isVisible(), true);
 +    QTRY_COMPARE(row->width(), 150.0);
 +    QTRY_COMPARE(row->height(), 50.0);
 +
 +    QTRY_COMPARE(two->x(), 50.0);
 +    QTRY_COMPARE(three->x(), 100.0);
 +
 +    delete canvas;
 +}
 +
++void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
++{
++    QFETCH(int, initialItemCount);
++    QFETCH(int, insertionIndex);
++    QFETCH(int, insertionCount);
++    QFETCH(ListRange, expectedDisplacedIndexes);
++
++    QPointF targetItems_transitionFrom(-50, -50);
++    QPointF displacedItems_transitionVia(100, 100);
++
++    QaimModel model;
++    for (int i = 0; i < initialItemCount; i++)
++        model.addItem("Original item" + QString::number(i), "");
++    QaimModel model_targetItems_transitionFrom;
++    QaimModel model_displacedItems_transitionVia;
++
++    QQuickView *canvas = QQuickViewTestUtil::createView();
++    QQmlContext *ctxt = canvas->rootContext();
++    ctxt->setContextProperty("enableAddTransition", true);
++    ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
++    ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
++    ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
++    ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
++    canvas->setSource(testFile("transitions.qml"));
++    canvas->show();
++    qApp->processEvents();
++
++    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
++
++    QQuickItem *positioner = canvas->rootObject()->findChild<QQuickItem*>(positionerObjectName);
++    QVERIFY(positioner);
++    positioner->findChild<QQuickItem*>("repeater")->setProperty("model", QVariant::fromValue(&model));
++
++    QList<QPair<QString, QString> > targetData;
++    QList<int> targetIndexes;
++    for (int i=0; i<model.count(); i++) {
++        targetData << qMakePair(model.name(i), model.number(i));
++        targetIndexes << i;
++    }
++    QList<QQuickItem *> targetItems = findItems<QQuickItem>(positioner, "wrapper", targetIndexes);
++
++    // check initial add transition
++    // (positioners run the add transition on all items that are initially created for the view)
++    QTRY_COMPARE(canvas->rootObject()->property("targetTransitionsDone").toInt(), initialItemCount);
++    QTRY_COMPARE(canvas->rootObject()->property("displaceTransitionsDone").toInt(), 0);
++    model_targetItems_transitionFrom.matchAgainst(targetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos");
++    matchItemsAndIndexes(canvas->rootObject()->property("targetTrans_items").toMap(), model, targetIndexes);
++    matchIndexLists(canvas->rootObject()->property("targetTrans_targetIndexes").toList(), targetIndexes);
++    matchItemLists(canvas->rootObject()->property("targetTrans_targetItems").toList(), targetItems);
++
++    model_targetItems_transitionFrom.clear();
++    canvas->rootObject()->setProperty("targetTransitionsDone", 0);
++    canvas->rootObject()->setProperty("targetTrans_items", QVariantMap());
++    canvas->rootObject()->setProperty("targetTrans_targetIndexes", QVariantList());
++    canvas->rootObject()->setProperty("targetTrans_targetItems", QVariantList());
++
++    // do insertion
++    targetData.clear();
++    targetIndexes.clear();
++    for (int i=insertionIndex; i<insertionIndex+insertionCount; i++) {
++        targetData << qMakePair(QString("New item %1").arg(i), QString(""));
++        targetIndexes << i;
++    }
++    model.insertItems(insertionIndex, targetData);
++    QTRY_COMPARE(model.count(), positioner->property("count").toInt());
++
++    targetItems = findItems<QQuickItem>(positioner, "wrapper", targetIndexes);
++
++    QTRY_COMPARE(canvas->rootObject()->property("targetTransitionsDone").toInt(), targetData.count());
++    QTRY_COMPARE(canvas->rootObject()->property("displaceTransitionsDone").toInt(), expectedDisplacedIndexes.count());
++
++    // check the target and displaced items were animated
++    model_targetItems_transitionFrom.matchAgainst(targetData, "wasn't animated from target 'from' pos", "shouldn't have been animated from target 'from' pos");
++    model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim");
++
++    // check attached properties
++    matchItemsAndIndexes(canvas->rootObject()->property("targetTrans_items").toMap(), model, targetIndexes);
++    matchIndexLists(canvas->rootObject()->property("targetTrans_targetIndexes").toList(), targetIndexes);
++    matchItemLists(canvas->rootObject()->property("targetTrans_targetItems").toList(), targetItems);
++    if (expectedDisplacedIndexes.isValid()) {
++        // adjust expectedDisplacedIndexes to their final values after the move
++        QList<int> displacedIndexes = adjustIndexesForAddDisplaced(expectedDisplacedIndexes.indexes, insertionIndex, insertionCount);
++        matchItemsAndIndexes(canvas->rootObject()->property("displacedTrans_items").toMap(), model, displacedIndexes);
++        matchIndexLists(canvas->rootObject()->property("displacedTrans_targetIndexes").toList(), targetIndexes);
++        matchItemLists(canvas->rootObject()->property("displacedTrans_targetItems").toList(), targetItems);
++    }
++
++    checkItemPositions(positioner, &model, 5.0);   // XXX fetch from qml?
++
++    delete canvas;
++}
++
++void tst_qquickpositioners::addTransitions_data()
++{
++    // If this data changes, update addTransitions_grid_data() also
++
++    QTest::addColumn<int>("initialItemCount");
++    QTest::addColumn<int>("insertionIndex");
++    QTest::addColumn<int>("insertionCount");
++    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
++
++    QTest::newRow("add one @ start") << 10 << 0 << 1 << ListRange(0, 9);
++    QTest::newRow("add one @ middle") << 10 << 5 << 1 << ListRange(5, 9);
++    QTest::newRow("add one @ end") << 10 << 10 << 1 << ListRange();
++
++    QTest::newRow("add multiple @ start") << 10 << 0 << 3 << ListRange(0, 9);
++    QTest::newRow("add multiple @ middle") << 10 << 5 << 3 << ListRange(5, 9);
++    QTest::newRow("add multiple @ end") << 10 << 10 << 3 << ListRange();
++}
++
++void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
++{
++    QFETCH(int, initialItemCount);
++    QFETCH(ListChange, change);
++    QFETCH(ListRange, expectedDisplacedIndexes);
++
++    QPointF targetItems_transitionFrom(-50, -50);
++    QPointF displacedItems_transitionVia(100, 100);
++
++    QaimModel model;
++    for (int i = 0; i < initialItemCount; i++)
++        model.addItem("Item" + QString::number(i), "");
++    QaimModel model_targetItems_transitionFrom;
++    QaimModel model_displacedItems_transitionVia;
++
++    QQuickView *canvas = QQuickViewTestUtil::createView();
++    QQmlContext *ctxt = canvas->rootContext();
++    ctxt->setContextProperty("enableAddTransition", false);
++    ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
++    ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
++    ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
++    ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
++    canvas->setSource(testFile("transitions.qml"));
++    canvas->show();
++    qApp->processEvents();
++
++    QList<QPair<QString,QString> > expectedDisplacedValues = expectedDisplacedIndexes.getModelDataValues(model);
++
++    QQuickItem *positioner = canvas->rootObject()->findChild<QQuickItem*>(positionerObjectName);
++    QVERIFY(positioner);
++    positioner->findChild<QQuickItem*>("repeater")->setProperty("model", QVariant::fromValue(&model));
++    QTRY_COMPARE(QQuickItemPrivate::get(positioner)->polishScheduled, false);
++
++    switch (change.type) {
++        case ListChange::Removed:
++            model.removeItems(change.index, change.count);
++            QTRY_COMPARE(model.count(), positioner->property("count").toInt());
++            break;
++        case ListChange::Moved:
++            model.moveItems(change.index, change.to, change.count);
++            QTRY_COMPARE(QQuickItemPrivate::get(positioner)->polishScheduled, false);
++            break;
++        case ListChange::Inserted:
++        case ListChange::SetCurrent:
++        case ListChange::SetContentY:
++            QVERIFY(false);
++            break;
++    }
++
++    QTRY_COMPARE(canvas->rootObject()->property("displaceTransitionsDone").toInt(), expectedDisplacedIndexes.count());
++    QCOMPARE(canvas->rootObject()->property("targetTransitionsDone").toInt(), 0);
++
++    // check the target and displaced items were animated
++    QCOMPARE(model_targetItems_transitionFrom.count(), 0);
++    model_displacedItems_transitionVia.matchAgainst(expectedDisplacedValues, "wasn't animated with displaced anim", "shouldn't have been animated with displaced anim");
++
++    // check attached properties
++    QCOMPARE(canvas->rootObject()->property("targetTrans_items").toMap().count(), 0);
++    QCOMPARE(canvas->rootObject()->property("targetTrans_targetIndexes").toList().count(), 0);
++    QCOMPARE(canvas->rootObject()->property("targetTrans_targetItems").toList().count(), 0);
++    if (expectedDisplacedIndexes.isValid()) {
++        // adjust expectedDisplacedIndexes to their final values after the move
++        QList<int> displacedIndexes;
++        if (change.type == ListChange::Inserted)
++            displacedIndexes = adjustIndexesForAddDisplaced(expectedDisplacedIndexes.indexes, change.index, change.count);
++        else if (change.type == ListChange::Moved)
++            displacedIndexes = adjustIndexesForMove(expectedDisplacedIndexes.indexes, change.index, change.to, change.count);
++        else if (change.type == ListChange::Removed)
++            displacedIndexes = adjustIndexesForRemoveDisplaced(expectedDisplacedIndexes.indexes, change.index, change.count);
++        else
++            QVERIFY(false);
++        matchItemsAndIndexes(canvas->rootObject()->property("displacedTrans_items").toMap(), model, displacedIndexes);
++
++        QVariantList listOfEmptyIntLists;
++        for (int i=0; i<displacedIndexes.count(); i++)
++            listOfEmptyIntLists << QVariant::fromValue(QList<int>());
++        QCOMPARE(canvas->rootObject()->property("displacedTrans_targetIndexes").toList(), listOfEmptyIntLists);
++        QVariantList listOfEmptyObjectLists;
++        for (int i=0; i<displacedIndexes.count(); i++)
++            listOfEmptyObjectLists.insert(listOfEmptyObjectLists.count(), QVariantList());
++        QCOMPARE(canvas->rootObject()->property("displacedTrans_targetItems").toList(), listOfEmptyObjectLists);
++    }
++
++    checkItemPositions(positioner, &model, 5.0);
++
++    delete canvas;
++}
++
++void tst_qquickpositioners::moveTransitions_data()
++{
++    // If this data changes, update moveTransitions_grid_data() also
++
++    QTest::addColumn<int>("initialItemCount");
++    QTest::addColumn<ListChange>("change");
++    QTest::addColumn<ListRange>("expectedDisplacedIndexes");
++
++    QTest::newRow("remove one @ start") << 10 << ListChange::remove(0, 1) << ListRange(1, 9);
++    QTest::newRow("remove one @ middle") << 10 << ListChange::remove(4, 1) << ListRange(5, 9);
++    QTest::newRow("remove one @ end") << 10 << ListChange::remove(9, 1) << ListRange();
++
++    QTest::newRow("remove multiple @ start") << 10 << ListChange::remove(0, 3) << ListRange(3, 9);
++    QTest::newRow("remove multiple @ middle") << 10 << ListChange::remove(4, 3) << ListRange(7, 9);
++    QTest::newRow("remove multiple @ end") << 10 << ListChange::remove(7, 3) << ListRange();
++}
++
++
++void tst_qquickpositioners::checkItemPositions(QQuickItem *positioner, QaimModel *model, qreal incrementalSize)
++{
++    QVERIFY(model->count() > 0);
++    qreal padding = 0;
++    qreal currentSize = 30;
++    qreal rowX = 0;
++    qreal rowY = 0;
++
++    for (int i=0; i<model->count(); ++i) {
++        QQuickItem *item = findItem<QQuickItem>(positioner, "wrapper", i);
++        QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
++
++        QCOMPARE(item->width(), currentSize);
++        QCOMPARE(item->height(), currentSize);
++
++        if (qobject_cast<QQuickRow*>(positioner)) {
++            QCOMPARE(item->x(), (i * 30.0) + padding);
++            QCOMPARE(item->y(), 0.0);
++        } else if (qobject_cast<QQuickColumn*>(positioner)) {
++            QCOMPARE(item->x(), 0.0);
++            QCOMPARE(item->y(), (i * 30.0) + padding);
++        } else if (qobject_cast<QQuickGrid*>(positioner)) {
++            int columns = 4;
++            int rows = qCeil(model->count() / qreal(columns));
++            int lastMatchingRowIndex = (rows * columns) - (columns - i%columns);
++            if (lastMatchingRowIndex >= model->count())
++                lastMatchingRowIndex -= columns;
++            if (i % columns > 0) {
++                QQuickItem *finalAlignedRowItem = findItem<QQuickItem>(positioner, "wrapper", lastMatchingRowIndex);
++                QVERIFY(finalAlignedRowItem);
++                QCOMPARE(item->x(), finalAlignedRowItem->x());
++            } else {
++                QCOMPARE(item->x(), 0.0);
++            }
++            if (i / columns > 0) {
++                QQuickItem *prevRowLastItem = findItem<QQuickItem>(positioner, "wrapper", (i/columns * columns) - 1);
++                QVERIFY(prevRowLastItem);
++                QCOMPARE(item->y(), prevRowLastItem->y() + prevRowLastItem->height());
++            } else {
++                QCOMPARE(item->y(), 0.0);
++            }
++        } else if (qobject_cast<QQuickFlow*>(positioner)) {
++            if (rowX + item->width() > positioner->width()) {
++                QQuickItem *prevItem = findItem<QQuickItem>(positioner, "wrapper", i-1);
++                QVERIFY(prevItem);
++                rowX = 0;
++                rowY = prevItem->y() + prevItem->height();
++            }
++            QCOMPARE(item->x(), rowX);
++            QCOMPARE(item->y(), rowY);
++            rowX += item->width();
++        } else {
++            QVERIFY2(false, "Unknown positioner type");
++        }
++        QQuickText *name = findItem<QQuickText>(positioner, "name", i);
++        QVERIFY(name != 0);
++        QTRY_COMPARE(name->text(), model->name(i));
++
++        padding += i * incrementalSize;
++        currentSize += incrementalSize;
++    }
++}
++
 +void tst_qquickpositioners::test_vertical()
 +{
 +    QQuickView *canvas = createView(testFile("vertical.qml"));
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 0.0);
 +    QCOMPARE(two->y(), 50.0);
 +    QCOMPARE(three->x(), 0.0);
 +    QCOMPARE(three->y(), 60.0);
 +
 +    QQuickItem *column = canvas->rootObject()->findChild<QQuickItem*>("column");
 +    QVERIFY(column);
 +    QCOMPARE(column->height(), 80.0);
 +    QCOMPARE(column->width(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_vertical_spacing()
 +{
 +    QQuickView *canvas = createView(testFile("vertical-spacing.qml"));
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 0.0);
 +    QCOMPARE(two->y(), 60.0);
 +    QCOMPARE(three->x(), 0.0);
 +    QCOMPARE(three->y(), 80.0);
 +
 +    QQuickItem *column = canvas->rootObject()->findChild<QQuickItem*>("column");
 +    QCOMPARE(column->height(), 100.0);
 +    QCOMPARE(column->width(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_vertical_animated()
 +{
 +    QQuickView *canvas = createView(testFile("vertical-animated.qml"), false);
 +
 +    //Note that they animate in
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QCOMPARE(one->y(), -100.0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QCOMPARE(two->y(), -100.0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QCOMPARE(three->y(), -100.0);
 +
 +    QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
 +
 +    QQuickItem *column = canvas->rootObject()->findChild<QQuickItem*>("column");
 +    QVERIFY(column);
 +    QCOMPARE(column->height(), 100.0);
 +    QCOMPARE(column->width(), 50.0);
 +
 +    //QTRY_COMPARE used instead of waiting for the expected time of animation completion
 +    //Note that this means the duration of the animation is NOT tested
 +
 +    QTRY_COMPARE(one->y(), 0.0);
 +    QTRY_COMPARE(one->x(), 0.0);
 +    QTRY_COMPARE(two->isVisible(), false);
 +    QTRY_COMPARE(two->y(), -100.0);//Not 'in' yet
 +    QTRY_COMPARE(two->x(), 0.0);
 +    QTRY_COMPARE(three->y(), 50.0);
 +    QTRY_COMPARE(three->x(), 0.0);
 +
 +    //Add 'two'
 +    two->setVisible(true);
 +    QTRY_COMPARE(two->isVisible(), true);
 +    QTRY_COMPARE(column->height(), 150.0);
 +    QTRY_COMPARE(column->width(), 50.0);
 +    QTest::qWait(0);//Let the animation start
 +    QVERIFY(two->y() >= -100.0 && two->y() < 50.0);
 +    QVERIFY(three->y() >= 50.0 && three->y() < 100.0);
 +
 +    QTRY_COMPARE(two->y(), 50.0);
 +    QTRY_COMPARE(three->y(), 100.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_grid()
 +{
 +    QQuickView *canvas = createView(testFile("gridtest.qml"));
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 50.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 70.0);
 +    QCOMPARE(three->y(), 0.0);
 +    QCOMPARE(four->x(), 0.0);
 +    QCOMPARE(four->y(), 50.0);
 +    QCOMPARE(five->x(), 50.0);
 +    QCOMPARE(five->y(), 50.0);
 +
 +    QQuickGrid *grid = canvas->rootObject()->findChild<QQuickGrid*>("grid");
 +    QCOMPARE(grid->flow(), QQuickGrid::LeftToRight);
 +    QCOMPARE(grid->width(), 100.0);
 +    QCOMPARE(grid->height(), 100.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_grid_topToBottom()
 +{
 +    QQuickView *canvas = createView(testFile("grid-toptobottom.qml"));
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 0.0);
 +    QCOMPARE(two->y(), 50.0);
 +    QCOMPARE(three->x(), 0.0);
 +    QCOMPARE(three->y(), 100.0);
 +    QCOMPARE(four->x(), 50.0);
 +    QCOMPARE(four->y(), 0.0);
 +    QCOMPARE(five->x(), 50.0);
 +    QCOMPARE(five->y(), 50.0);
 +
 +    QQuickGrid *grid = canvas->rootObject()->findChild<QQuickGrid*>("grid");
 +    QCOMPARE(grid->flow(), QQuickGrid::TopToBottom);
 +    QCOMPARE(grid->width(), 100.0);
 +    QCOMPARE(grid->height(), 120.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_grid_rightToLeft()
 +{
 +    QQuickView *canvas = createView(testFile("gridtest.qml"));
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", true);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QCOMPARE(one->x(), 50.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 30.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 0.0);
 +    QCOMPARE(three->y(), 0.0);
 +    QCOMPARE(four->x(), 50.0);
 +    QCOMPARE(four->y(), 50.0);
 +    QCOMPARE(five->x(), 40.0);
 +    QCOMPARE(five->y(), 50.0);
 +
 +    QQuickGrid *grid = canvas->rootObject()->findChild<QQuickGrid*>("grid");
 +    QCOMPARE(grid->layoutDirection(), Qt::RightToLeft);
 +    QCOMPARE(grid->width(), 100.0);
 +    QCOMPARE(grid->height(), 100.0);
 +
 +    // Change the width of the grid and check that items stay to the right
 +    grid->setWidth(200);
 +    QTRY_COMPARE(one->x(), 150.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 130.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 100.0);
 +    QCOMPARE(three->y(), 0.0);
 +    QCOMPARE(four->x(), 150.0);
 +    QCOMPARE(four->y(), 50.0);
 +    QCOMPARE(five->x(), 140.0);
 +    QCOMPARE(five->y(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_grid_spacing()
 +{
 +    QQuickView *canvas = createView(testFile("grid-spacing.qml"));
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 54.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 78.0);
 +    QCOMPARE(three->y(), 0.0);
 +    QCOMPARE(four->x(), 0.0);
 +    QCOMPARE(four->y(), 54.0);
 +    QCOMPARE(five->x(), 54.0);
 +    QCOMPARE(five->y(), 54.0);
 +
 +    QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
 +    QCOMPARE(grid->width(), 128.0);
 +    QCOMPARE(grid->height(), 104.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_grid_row_column_spacing()
 +{
 +    QQuickView *canvas = createView(testFile("grid-row-column-spacing.qml"));
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 61.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 92.0);
 +    QCOMPARE(three->y(), 0.0);
 +    QCOMPARE(four->x(), 0.0);
 +    QCOMPARE(four->y(), 57.0);
 +    QCOMPARE(five->x(), 61.0);
 +    QCOMPARE(five->y(), 57.0);
 +
 +    QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
 +    QCOMPARE(grid->width(), 142.0);
 +    QCOMPARE(grid->height(), 107.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_grid_animated()
 +{
 +    QQuickView *canvas = createView(testFile("grid-animated.qml"), false);
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", false);
 +
 +    //Note that all animate in
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QCOMPARE(one->x(), -100.0);
 +    QCOMPARE(one->y(), -100.0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QCOMPARE(two->x(), -100.0);
 +    QCOMPARE(two->y(), -100.0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QCOMPARE(three->x(), -100.0);
 +    QCOMPARE(three->y(), -100.0);
 +
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QCOMPARE(four->x(), -100.0);
 +    QCOMPARE(four->y(), -100.0);
 +
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +    QCOMPARE(five->x(), -100.0);
 +    QCOMPARE(five->y(), -100.0);
 +
 +    QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
 +
 +    QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
 +    QVERIFY(grid);
 +    QCOMPARE(grid->width(), 150.0);
 +    QCOMPARE(grid->height(), 100.0);
 +
 +    //QTRY_COMPARE used instead of waiting for the expected time of animation completion
 +    //Note that this means the duration of the animation is NOT tested
 +
 +    QTRY_COMPARE(one->y(), 0.0);
 +    QTRY_COMPARE(one->x(), 0.0);
 +    QTRY_COMPARE(two->isVisible(), false);
 +    QTRY_COMPARE(two->y(), -100.0);
 +    QTRY_COMPARE(two->x(), -100.0);
 +    QTRY_COMPARE(three->y(), 0.0);
 +    QTRY_COMPARE(three->x(), 50.0);
 +    QTRY_COMPARE(four->y(), 0.0);
 +    QTRY_COMPARE(four->x(), 100.0);
 +    QTRY_COMPARE(five->y(), 50.0);
 +    QTRY_COMPARE(five->x(), 0.0);
 +
 +    //Add 'two'
 +    two->setVisible(true);
 +    QCOMPARE(two->isVisible(), true);
 +    QCOMPARE(grid->width(), 150.0);
 +    QCOMPARE(grid->height(), 100.0);
 +    QTest::qWait(0);//Let the animation start
 +    QCOMPARE(two->x(), -100.0);
 +    QCOMPARE(two->y(), -100.0);
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(three->x(), 50.0);
 +    QCOMPARE(three->y(), 0.0);
 +    QCOMPARE(four->x(), 100.0);
 +    QCOMPARE(four->y(), 0.0);
 +    QCOMPARE(five->x(), 0.0);
 +    QCOMPARE(five->y(), 50.0);
 +    //Let the animation complete
 +    QTRY_COMPARE(two->x(), 50.0);
 +    QTRY_COMPARE(two->y(), 0.0);
 +    QTRY_COMPARE(one->x(), 0.0);
 +    QTRY_COMPARE(one->y(), 0.0);
 +    QTRY_COMPARE(three->x(), 100.0);
 +    QTRY_COMPARE(three->y(), 0.0);
 +    QTRY_COMPARE(four->x(), 0.0);
 +    QTRY_COMPARE(four->y(), 50.0);
 +    QTRY_COMPARE(five->x(), 50.0);
 +    QTRY_COMPARE(five->y(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_grid_animated_rightToLeft()
 +{
 +    QQuickView *canvas = createView(testFile("grid-animated.qml"), false);
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", true);
 +
 +    //Note that all animate in
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QCOMPARE(one->x(), -100.0);
 +    QCOMPARE(one->y(), -100.0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QCOMPARE(two->x(), -100.0);
 +    QCOMPARE(two->y(), -100.0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QCOMPARE(three->x(), -100.0);
 +    QCOMPARE(three->y(), -100.0);
 +
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QCOMPARE(four->x(), -100.0);
 +    QCOMPARE(four->y(), -100.0);
 +
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +    QCOMPARE(five->x(), -100.0);
 +    QCOMPARE(five->y(), -100.0);
 +
 +    QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
 +
 +    QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
 +    QVERIFY(grid);
 +    QCOMPARE(grid->width(), 150.0);
 +    QCOMPARE(grid->height(), 100.0);
 +
 +    //QTRY_COMPARE used instead of waiting for the expected time of animation completion
 +    //Note that this means the duration of the animation is NOT tested
 +
 +    QTRY_COMPARE(one->y(), 0.0);
 +    QTRY_COMPARE(one->x(), 100.0);
 +    QTRY_COMPARE(two->isVisible(), false);
 +    QTRY_COMPARE(two->y(), -100.0);
 +    QTRY_COMPARE(two->x(), -100.0);
 +    QTRY_COMPARE(three->y(), 0.0);
 +    QTRY_COMPARE(three->x(), 50.0);
 +    QTRY_COMPARE(four->y(), 0.0);
 +    QTRY_COMPARE(four->x(), 0.0);
 +    QTRY_COMPARE(five->y(), 50.0);
 +    QTRY_COMPARE(five->x(), 100.0);
 +
 +    //Add 'two'
 +    two->setVisible(true);
 +    QCOMPARE(two->isVisible(), true);
 +    QCOMPARE(grid->width(), 150.0);
 +    QCOMPARE(grid->height(), 100.0);
 +    QTest::qWait(0);//Let the animation start
 +    QCOMPARE(two->x(), -100.0);
 +    QCOMPARE(two->y(), -100.0);
 +    QCOMPARE(one->x(), 100.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(three->x(), 50.0);
 +    QCOMPARE(three->y(), 0.0);
 +    QCOMPARE(four->x(), 0.0);
 +    QCOMPARE(four->y(), 0.0);
 +    QCOMPARE(five->x(), 100.0);
 +    QCOMPARE(five->y(), 50.0);
 +    //Let the animation complete
 +    QTRY_COMPARE(two->x(), 50.0);
 +    QTRY_COMPARE(two->y(), 0.0);
 +    QTRY_COMPARE(one->x(), 100.0);
 +    QTRY_COMPARE(one->y(), 0.0);
 +    QTRY_COMPARE(three->x(), 0.0);
 +    QTRY_COMPARE(three->y(), 0.0);
 +    QTRY_COMPARE(four->x(), 100.0);
 +    QTRY_COMPARE(four->y(), 50.0);
 +    QTRY_COMPARE(five->x(), 50.0);
 +    QTRY_COMPARE(five->y(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_grid_zero_columns()
 +{
 +    QQuickView *canvas = createView(testFile("gridzerocolumns.qml"));
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 50.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 70.0);
 +    QCOMPARE(three->y(), 0.0);
 +    QCOMPARE(four->x(), 120.0);
 +    QCOMPARE(four->y(), 0.0);
 +    QCOMPARE(five->x(), 0.0);
 +    QCOMPARE(five->y(), 50.0);
 +
 +    QQuickItem *grid = canvas->rootObject()->findChild<QQuickItem*>("grid");
 +    QCOMPARE(grid->width(), 170.0);
 +    QCOMPARE(grid->height(), 60.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_propertychanges()
 +{
 +    QQuickView *canvas = createView(testFile("propertychangestest.qml"));
 +
 +    QQuickGrid *grid = qobject_cast<QQuickGrid*>(canvas->rootObject());
 +    QVERIFY(grid != 0);
 +    QQuickTransition *rowTransition = canvas->rootObject()->findChild<QQuickTransition*>("rowTransition");
 +    QQuickTransition *columnTransition = canvas->rootObject()->findChild<QQuickTransition*>("columnTransition");
 +
 +    QSignalSpy addSpy(grid, SIGNAL(addChanged()));
 +    QSignalSpy moveSpy(grid, SIGNAL(moveChanged()));
 +    QSignalSpy columnsSpy(grid, SIGNAL(columnsChanged()));
 +    QSignalSpy rowsSpy(grid, SIGNAL(rowsChanged()));
 +
 +    QVERIFY(grid);
 +    QVERIFY(rowTransition);
 +    QVERIFY(columnTransition);
 +    QCOMPARE(grid->add(), columnTransition);
 +    QCOMPARE(grid->move(), columnTransition);
 +    QCOMPARE(grid->columns(), 4);
 +    QCOMPARE(grid->rows(), -1);
 +
 +    grid->setAdd(rowTransition);
 +    grid->setMove(rowTransition);
 +    QCOMPARE(grid->add(), rowTransition);
 +    QCOMPARE(grid->move(), rowTransition);
 +    QCOMPARE(addSpy.count(),1);
 +    QCOMPARE(moveSpy.count(),1);
 +
 +    grid->setAdd(rowTransition);
 +    grid->setMove(rowTransition);
 +    QCOMPARE(addSpy.count(),1);
 +    QCOMPARE(moveSpy.count(),1);
 +
 +    grid->setAdd(0);
 +    grid->setMove(0);
 +    QCOMPARE(addSpy.count(),2);
 +    QCOMPARE(moveSpy.count(),2);
 +
 +    grid->setColumns(-1);
 +    grid->setRows(3);
 +    QCOMPARE(grid->columns(), -1);
 +    QCOMPARE(grid->rows(), 3);
 +    QCOMPARE(columnsSpy.count(),1);
 +    QCOMPARE(rowsSpy.count(),1);
 +
 +    grid->setColumns(-1);
 +    grid->setRows(3);
 +    QCOMPARE(columnsSpy.count(),1);
 +    QCOMPARE(rowsSpy.count(),1);
 +
 +    grid->setColumns(2);
 +    grid->setRows(2);
 +    QCOMPARE(columnsSpy.count(),2);
 +    QCOMPARE(rowsSpy.count(),2);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_repeater()
 +{
 +    QQuickView *canvas = createView(testFile("repeatertest.qml"));
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 50.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 100.0);
 +    QCOMPARE(three->y(), 0.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_flow()
 +{
 +    QQuickView *canvas = createView(testFile("flowtest.qml"));
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", false);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 50.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 0.0);
 +    QCOMPARE(three->y(), 50.0);
 +    QCOMPARE(four->x(), 0.0);
 +    QCOMPARE(four->y(), 70.0);
 +    QCOMPARE(five->x(), 50.0);
 +    QCOMPARE(five->y(), 70.0);
 +
 +    QQuickItem *flow = canvas->rootObject()->findChild<QQuickItem*>("flow");
 +    QVERIFY(flow);
 +    QCOMPARE(flow->width(), 90.0);
 +    QCOMPARE(flow->height(), 120.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_flow_rightToLeft()
 +{
 +    QQuickView *canvas = createView(testFile("flowtest.qml"));
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", true);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QCOMPARE(one->x(), 40.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 20.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 40.0);
 +    QCOMPARE(three->y(), 50.0);
 +    QCOMPARE(four->x(), 40.0);
 +    QCOMPARE(four->y(), 70.0);
 +    QCOMPARE(five->x(), 30.0);
 +    QCOMPARE(five->y(), 70.0);
 +
 +    QQuickItem *flow = canvas->rootObject()->findChild<QQuickItem*>("flow");
 +    QVERIFY(flow);
 +    QCOMPARE(flow->width(), 90.0);
 +    QCOMPARE(flow->height(), 120.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_flow_topToBottom()
 +{
 +    QQuickView *canvas = createView(testFile("flowtest-toptobottom.qml"));
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", false);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QCOMPARE(one->x(), 0.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 50.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 50.0);
 +    QCOMPARE(three->y(), 50.0);
 +    QCOMPARE(four->x(), 100.0);
 +    QCOMPARE(four->y(), 00.0);
 +    QCOMPARE(five->x(), 100.0);
 +    QCOMPARE(five->y(), 50.0);
 +
 +    QQuickItem *flow = canvas->rootObject()->findChild<QQuickItem*>("flow");
 +    QVERIFY(flow);
 +    QCOMPARE(flow->height(), 90.0);
 +    QCOMPARE(flow->width(), 150.0);
 +
 +    canvas->rootObject()->setProperty("testRightToLeft", true);
 +
 +    QVERIFY(flow);
 +    QCOMPARE(flow->height(), 90.0);
 +    QCOMPARE(flow->width(), 150.0);
 +
 +    QCOMPARE(one->x(), 100.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 80.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 50.0);
 +    QCOMPARE(three->y(), 50.0);
 +    QCOMPARE(four->x(), 0.0);
 +    QCOMPARE(four->y(), 0.0);
 +    QCOMPARE(five->x(), 40.0);
 +    QCOMPARE(five->y(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_flow_resize()
 +{
 +    QQuickView *canvas = createView(testFile("flowtest.qml"));
 +
 +    QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
 +    QVERIFY(root);
 +    root->setWidth(125);
 +    root->setProperty("testRightToLeft", false);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QVERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QTRY_COMPARE(one->x(), 0.0);
 +    QTRY_COMPARE(one->y(), 0.0);
 +    QTRY_COMPARE(two->x(), 50.0);
 +    QTRY_COMPARE(two->y(), 0.0);
 +    QTRY_COMPARE(three->x(), 70.0);
 +    QTRY_COMPARE(three->y(), 0.0);
 +    QTRY_COMPARE(four->x(), 0.0);
 +    QTRY_COMPARE(four->y(), 50.0);
 +    QTRY_COMPARE(five->x(), 50.0);
 +    QTRY_COMPARE(five->y(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_flow_resize_rightToLeft()
 +{
 +    QQuickView *canvas = createView(testFile("flowtest.qml"));
 +
 +    QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
 +    QVERIFY(root);
 +    root->setWidth(125);
 +    root->setProperty("testRightToLeft", true);
 +
 +    QQuickRectangle *one = canvas->rootObject()->findChild<QQuickRectangle*>("one");
 +    QTRY_VERIFY(one != 0);
 +    QQuickRectangle *two = canvas->rootObject()->findChild<QQuickRectangle*>("two");
 +    QVERIFY(two != 0);
 +    QQuickRectangle *three = canvas->rootObject()->findChild<QQuickRectangle*>("three");
 +    QVERIFY(three != 0);
 +    QQuickRectangle *four = canvas->rootObject()->findChild<QQuickRectangle*>("four");
 +    QVERIFY(four != 0);
 +    QQuickRectangle *five = canvas->rootObject()->findChild<QQuickRectangle*>("five");
 +    QVERIFY(five != 0);
 +
 +    QCOMPARE(one->x(), 75.0);
 +    QCOMPARE(one->y(), 0.0);
 +    QCOMPARE(two->x(), 55.0);
 +    QCOMPARE(two->y(), 0.0);
 +    QCOMPARE(three->x(), 5.0);
 +    QCOMPARE(three->y(), 0.0);
 +    QCOMPARE(four->x(), 75.0);
 +    QCOMPARE(four->y(), 50.0);
 +    QCOMPARE(five->x(), 65.0);
 +    QCOMPARE(five->y(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_flow_implicit_resize()
 +{
 +    QQuickView *canvas = createView(testFile("flow-testimplicitsize.qml"));
 +    QVERIFY(canvas->rootObject() != 0);
 +
 +    QQuickFlow *flow = canvas->rootObject()->findChild<QQuickFlow*>("flow");
 +    QVERIFY(flow != 0);
 +
 +    QCOMPARE(flow->width(), 100.0);
 +    QCOMPARE(flow->height(), 120.0);
 +
 +    canvas->rootObject()->setProperty("flowLayout", 0);
 +    QCOMPARE(flow->flow(), QQuickFlow::LeftToRight);
 +    QCOMPARE(flow->width(), 220.0);
 +    QCOMPARE(flow->height(), 50.0);
 +
 +    canvas->rootObject()->setProperty("flowLayout", 1);
 +    QCOMPARE(flow->flow(), QQuickFlow::TopToBottom);
 +    QCOMPARE(flow->width(), 100.0);
 +    QCOMPARE(flow->height(), 120.0);
 +
 +    canvas->rootObject()->setProperty("flowLayout", 2);
 +    QCOMPARE(flow->layoutDirection(), Qt::RightToLeft);
 +    QCOMPARE(flow->width(), 220.0);
 +    QCOMPARE(flow->height(), 50.0);
 +
 +    delete canvas;
 +}
 +
 +QString warningMessage;
 +
 +void interceptWarnings(QtMsgType type, const char *msg)
 +{
 +    Q_UNUSED( type );
 +    warningMessage = msg;
 +}
 +
 +void tst_qquickpositioners::test_conflictinganchors()
 +{
 +    QtMsgHandler oldMsgHandler = qInstallMsgHandler(interceptWarnings);
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine);
 +
 +    component.setData("import QtQuick 2.0\nColumn { Item { width: 100; height: 100; } }", QUrl::fromLocalFile(""));
 +    QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QVERIFY(warningMessage.isEmpty());
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nRow { Item { width: 100; height: 100; } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QVERIFY(warningMessage.isEmpty());
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nGrid { Item { width: 100; height: 100; } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QVERIFY(warningMessage.isEmpty());
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nFlow { Item { width: 100; height: 100; } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QVERIFY(warningMessage.isEmpty());
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nColumn { Item { width: 100; height: 100; anchors.top: parent.top } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QCOMPARE(warningMessage, QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function."));
 +    warningMessage.clear();
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nColumn { Item { width: 100; height: 100; anchors.centerIn: parent } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QCOMPARE(warningMessage, QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column. Column will not function."));
 +    warningMessage.clear();
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nColumn { Item { width: 100; height: 100; anchors.left: parent.left } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QVERIFY(warningMessage.isEmpty());
 +    warningMessage.clear();
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nRow { Item { width: 100; height: 100; anchors.left: parent.left } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QCOMPARE(warningMessage, QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function."));
 +    warningMessage.clear();
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nRow { width: 100; height: 100; Item { anchors.fill: parent } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QCOMPARE(warningMessage, QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row. Row will not function."));
 +    warningMessage.clear();
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nRow { Item { width: 100; height: 100; anchors.top: parent.top } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QVERIFY(warningMessage.isEmpty());
 +    warningMessage.clear();
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nGrid { Item { width: 100; height: 100; anchors.horizontalCenter: parent.horizontalCenter } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QCOMPARE(warningMessage, QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid. Grid will not function."));
 +    warningMessage.clear();
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nGrid { Item { width: 100; height: 100; anchors.centerIn: parent } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QCOMPARE(warningMessage, QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid. Grid will not function."));
 +    warningMessage.clear();
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nFlow { Item { width: 100; height: 100; anchors.verticalCenter: parent.verticalCenter } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow. Flow will not function."));
 +    delete item;
 +
 +    component.setData("import QtQuick 2.0\nFlow {  width: 100; height: 100; Item { anchors.fill: parent } }", QUrl::fromLocalFile(""));
 +    item = qobject_cast<QQuickItem*>(component.create());
 +    QVERIFY(item);
 +    QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow. Flow will not function."));
 +    qInstallMsgHandler(oldMsgHandler);
 +    delete item;
 +}
 +
 +void tst_qquickpositioners::test_mirroring()
 +{
 +    QList<QString> qmlFiles;
 +    qmlFiles << "horizontal.qml" << "gridtest.qml" << "flowtest.qml";
 +    QList<QString> objectNames;
 +    objectNames << "one" << "two" << "three" << "four" << "five";
 +
 +    foreach (const QString qmlFile, qmlFiles) {
 +        QQuickView *canvasA = createView(testFile(qmlFile));
 +        QQuickItem *rootA = qobject_cast<QQuickItem*>(canvasA->rootObject());
 +
 +        QQuickView *canvasB = createView(testFile(qmlFile));
 +        QQuickItem *rootB = qobject_cast<QQuickItem*>(canvasB->rootObject());
 +
 +        rootA->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
 +
 +        // LTR != RTL
 +        foreach (const QString objectName, objectNames) {
 +            // horizontal.qml only has three items
 +            if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
 +                break;
 +            QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
 +            QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
 +            QTRY_VERIFY(itemA->x() != itemB->x());
 +        }
 +
 +        QQmlProperty enabledProp(rootB, "LayoutMirroring.enabled", qmlContext(rootB));
 +        enabledProp.write(true);
 +        QQmlProperty inheritProp(rootB, "LayoutMirroring.childrenInherit", qmlContext(rootB));
 +        inheritProp.write(true);
 +
 +        // RTL == mirror
 +        foreach (const QString objectName, objectNames) {
 +            // horizontal.qml only has three items
 +            if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
 +                break;
 +            QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
 +            QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
 +            QTRY_COMPARE(itemA->x(), itemB->x());
 +        }
 +
 +        rootA->setProperty("testRightToLeft", false); // layoutDirection: Qt.LeftToRight
 +        rootB->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
 +
 +        // LTR == RTL + mirror
 +        foreach (const QString objectName, objectNames) {
 +            // horizontal.qml only has three items
 +            if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
 +                break;
 +            QQuickItem *itemA = rootA->findChild<QQuickItem*>(objectName);
 +            QQuickItem *itemB = rootB->findChild<QQuickItem*>(objectName);
 +            QTRY_COMPARE(itemA->x(), itemB->x());
 +        }
 +        delete canvasA;
 +        delete canvasB;
 +    }
 +}
 +
 +void tst_qquickpositioners::test_allInvisible()
 +{
 +    //QTBUG-19361
 +    QQuickView *canvas = createView(testFile("allInvisible.qml"));
 +
 +    QQuickItem *root = qobject_cast<QQuickItem*>(canvas->rootObject());
 +    QVERIFY(root);
 +
 +    QQuickRow *row = canvas->rootObject()->findChild<QQuickRow*>("row");
 +    QVERIFY(row != 0);
 +    QVERIFY(row->width() == 0);
 +    QVERIFY(row->height() == 0);
 +    QQuickColumn *column = canvas->rootObject()->findChild<QQuickColumn*>("column");
 +    QVERIFY(column != 0);
 +    QVERIFY(column->width() == 0);
 +    QVERIFY(column->height() == 0);
 +}
 +
 +void tst_qquickpositioners::test_attachedproperties()
 +{
 +    QFETCH(QString, filename);
 +
 +    QQuickView *canvas = createView(filename);
 +    QVERIFY(canvas->rootObject() != 0);
 +
 +    QQuickRectangle *greenRect = canvas->rootObject()->findChild<QQuickRectangle *>("greenRect");
 +    QVERIFY(greenRect != 0);
 +
 +    int posIndex = greenRect->property("posIndex").toInt();
 +    QVERIFY(posIndex == 0);
 +    bool isFirst = greenRect->property("isFirstItem").toBool();
 +    QVERIFY(isFirst == true);
 +    bool isLast = greenRect->property("isLastItem").toBool();
 +    QVERIFY(isLast == false);
 +
 +    QQuickRectangle *yellowRect = canvas->rootObject()->findChild<QQuickRectangle *>("yellowRect");
 +    QVERIFY(yellowRect != 0);
 +
 +    posIndex = yellowRect->property("posIndex").toInt();
 +    QVERIFY(posIndex == -1);
 +    isFirst = yellowRect->property("isFirstItem").toBool();
 +    QVERIFY(isFirst == false);
 +    isLast = yellowRect->property("isLastItem").toBool();
 +    QVERIFY(isLast == false);
 +
 +    yellowRect->metaObject()->invokeMethod(yellowRect, "onDemandPositioner");
 +
 +    posIndex = yellowRect->property("posIndex").toInt();
 +    QVERIFY(posIndex == 1);
 +    isFirst = yellowRect->property("isFirstItem").toBool();
 +    QVERIFY(isFirst == false);
 +    isLast = yellowRect->property("isLastItem").toBool();
 +    QVERIFY(isLast == true);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquickpositioners::test_attachedproperties_data()
 +{
 +    QTest::addColumn<QString>("filename");
 +
 +    QTest::newRow("column") << testFile("attachedproperties-column.qml");
 +    QTest::newRow("row") << testFile("attachedproperties-row.qml");
 +    QTest::newRow("grid") << testFile("attachedproperties-grid.qml");
 +    QTest::newRow("flow") << testFile("attachedproperties-flow.qml");
 +}
 +
 +void tst_qquickpositioners::test_attachedproperties_dynamic()
 +{
 +    QQuickView *canvas = createView(testFile("attachedproperties-dynamic.qml"));
 +    QVERIFY(canvas->rootObject() != 0);
 +
 +    QQuickRow *row = canvas->rootObject()->findChild<QQuickRow *>("pos");
 +    QVERIFY(row != 0);
 +
 +    QQuickRectangle *rect0 = canvas->rootObject()->findChild<QQuickRectangle *>("rect0");
 +    QVERIFY(rect0 != 0);
 +
 +    int posIndex = rect0->property("index").toInt();
 +    QVERIFY(posIndex == 0);
 +    bool isFirst = rect0->property("firstItem").toBool();
 +    QVERIFY(isFirst == true);
 +    bool isLast = rect0->property("lastItem").toBool();
 +    QVERIFY(isLast == false);
 +
 +    QQuickRectangle *rect1 = canvas->rootObject()->findChild<QQuickRectangle *>("rect1");
 +    QVERIFY(rect1 != 0);
 +
 +    posIndex = rect1->property("index").toInt();
 +    QVERIFY(posIndex == 1);
 +    isFirst = rect1->property("firstItem").toBool();
 +    QVERIFY(isFirst == false);
 +    isLast = rect1->property("lastItem").toBool();
 +    QVERIFY(isLast == true);
 +
 +    row->metaObject()->invokeMethod(row, "createSubRect");
 +
 +    QTRY_VERIFY(rect1->property("index").toInt() == 1);
 +    QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
 +    QTRY_VERIFY(rect1->property("lastItem").toBool() == false);
 +
 +    QQuickRectangle *rect2 = canvas->rootObject()->findChild<QQuickRectangle *>("rect2");
 +    QVERIFY(rect2 != 0);
 +
 +    posIndex = rect2->property("index").toInt();
 +    QVERIFY(posIndex == 2);
 +    isFirst = rect2->property("firstItem").toBool();
 +    QVERIFY(isFirst == false);
 +    isLast = rect2->property("lastItem").toBool();
 +    QVERIFY(isLast == true);
 +
 +    row->metaObject()->invokeMethod(row, "destroySubRect");
 +
 +    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 +    QCoreApplication::processEvents();
 +
 +    QTRY_VERIFY(rect1->property("index").toInt() == 1);
 +    QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
 +    QTRY_VERIFY(rect1->property("lastItem").toBool() == true);
 +
 +    delete canvas;
 +}
 +
 +QQuickView *tst_qquickpositioners::createView(const QString &filename, bool wait)
 +{
 +    QQuickView *canvas = new QQuickView(0);
 +
 +    canvas->setSource(QUrl::fromLocalFile(filename));
 +    canvas->show();
 +    if (wait)
 +        QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
 +
 +    return canvas;
 +}
 +
++void tst_qquickpositioners::matchIndexLists(const QVariantList &indexLists, const QList<int> &expectedIndexes)
++{
++    for (int i=0; i<indexLists.count(); i++) {
++        QSet<int> current = indexLists[i].value<QList<int> >().toSet();
++        if (current != expectedIndexes.toSet())
++            qDebug() << "Cannot match actual targets" << current << "with expected" << expectedIndexes;
++        QCOMPARE(current, expectedIndexes.toSet());
++    }
++}
++
++void tst_qquickpositioners::matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList<int> &expectedIndexes)
++{
++    for (QVariantMap::const_iterator it = items.begin(); it != items.end(); ++it) {
++        QVERIFY(it.value().type() == QVariant::Int);
++        QString name = it.key();
++        int itemIndex = it.value().toInt();
++        QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex)));
++        if (model.name(itemIndex) != name)
++            qDebug() << itemIndex;
++        QCOMPARE(model.name(itemIndex), name);
++    }
++    QCOMPARE(items.count(), expectedIndexes.count());
++}
++
++void tst_qquickpositioners::matchItemLists(const QVariantList &itemLists, const QList<QQuickItem *> &expectedItems)
++{
++    for (int i=0; i<itemLists.count(); i++) {
++        QVERIFY(itemLists[i].type() == QVariant::List);
++        QVariantList current = itemLists[i].toList();
++        for (int j=0; j<current.count(); j++) {
++            QQuickItem *o = qobject_cast<QQuickItem*>(current[j].value<QObject*>());
++            QVERIFY2(o, QTest::toString(QString("Invalid actual item at %1").arg(j)));
++            QVERIFY2(expectedItems.contains(o), QTest::toString(QString("Cannot match item %1").arg(j)));
++        }
++        QCOMPARE(current.count(), expectedItems.count());
++    }
++}
 +
 +QTEST_MAIN(tst_qquickpositioners)
 +
 +#include "tst_qquickpositioners.moc"
index 0000000,0000000..f9a5d5f
new file mode 100644 (file)
Binary files differ
index 0000000,0000000..3dabd06
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,15 @@@
++CONFIG += testcase
++TARGET = tst_qquickspritesequence
++SOURCES += tst_qquickspritesequence.cpp
++
++include (../../shared/util.pri)
++
++macx:CONFIG -= app_bundle
++
++testDataFiles.files = data
++testDataFiles.path = .
++DEPLOYMENT += testDataFiles
++
++CONFIG += parallel_test
++
++QT += core-private gui-private qml-private quick-private network testlib
index 0000000,0000000..8469a94
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,98 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the test suite of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++#include <QtTest/QtTest>
++#include "../../shared/util.h"
++#include <QtQuick/qquickview.h>
++#include <private/qquickspritesequence_p.h>
++
++class tst_qquickspritesequence : public QQmlDataTest
++{
++    Q_OBJECT
++public:
++    tst_qquickspritesequence(){}
++
++private slots:
++    void test_properties();
++    void test_framerateAdvance();//Separate codepath for QQuickSpriteEngine
++};
++
++void tst_qquickspritesequence::test_properties()
++{
++    QQuickView *canvas = new QQuickView(0);
++
++    canvas->setSource(testFileUrl("basic.qml"));
++    canvas->show();
++    QTest::qWaitForWindowShown(canvas);
++
++    QVERIFY(canvas->rootObject());
++    QQuickSpriteSequence* sprite = canvas->rootObject()->findChild<QQuickSpriteSequence*>("sprite");
++    QVERIFY(sprite);
++
++    QVERIFY(sprite->running());
++    QVERIFY(sprite->interpolate());
++
++    sprite->setRunning(false);
++    QVERIFY(!sprite->running());
++    sprite->setInterpolate(false);
++    QVERIFY(!sprite->interpolate());
++
++    delete canvas;
++}
++
++void tst_qquickspritesequence::test_framerateAdvance()
++{
++    QQuickView *canvas = new QQuickView(0);
++
++    canvas->setSource(testFileUrl("advance.qml"));
++    canvas->show();
++    QTest::qWaitForWindowShown(canvas);
++
++    QVERIFY(canvas->rootObject());
++    QQuickSpriteSequence* sprite = canvas->rootObject()->findChild<QQuickSpriteSequence*>("sprite");
++    QVERIFY(sprite);
++
++    QTRY_COMPARE(sprite->currentSprite(), QLatin1String("secondState"));
++    delete canvas;
++}
++
++QTEST_MAIN(tst_qquickspritesequence)
++
++#include "tst_qquickspritesequence.moc"
index 86874b8,0000000..35ce724
mode 100644,000000..100644
--- /dev/null
@@@ -1,185 -1,0 +1,189 @@@
-     QTest::newRow("bold") << "<b>bold</b>" << "bold" << (FormatList() << Format(Format::Bold, 0, 4));
-     QTest::newRow("italic") << "<i>italic</i>" << "italic" << (FormatList() << Format(Format::Italic, 0, 6));
-     QTest::newRow("underline") << "<u>underline</u>" << "underline" << (FormatList() << Format(Format::Underline, 0, 9));
-     QTest::newRow("strong") << "<strong>strong</strong>" << "strong" << (FormatList() << Format(Format::Bold, 0, 6));
-     QTest::newRow("underline") << "<u>underline</u>" << "underline" << (FormatList() << Format(Format::Underline, 0, 9));
-     QTest::newRow("missing >") << "<b>text</b" << "text" << (FormatList() << Format(Format::Bold, 0, 4));
-     QTest::newRow("missing b>") << "<b>text</" << "text" << (FormatList() << Format(Format::Bold, 0, 4));
-     QTest::newRow("missing /b>") << "<b>text<" << "text" << (FormatList() << Format(Format::Bold, 0, 4));
-     QTest::newRow("missing </b>") << "<b>text" << "text" << (FormatList() << Format(Format::Bold, 0, 4));
-     QTest::newRow("nested") << "<b>text <i>italic</i> bold</b>" << "text italic bold" << (FormatList() << Format(Format::Bold, 0, 5) << Format(Format::Bold | Format::Italic, 5, 6) << Format(Format::Bold, 11, 5));
-     QTest::newRow("bad nest") << "<b>text <i>italic</b></i>" << "text italic" << (FormatList() << Format(Format::Bold, 0, 5) << Format(Format::Bold | Format::Italic, 5, 6));
-     QTest::newRow("font color") << "<font color=\"red\">red text</font>" << "red text" << (FormatList() << Format(0, 0, 8));
-     QTest::newRow("font color: single quote") << "<font color='red'>red text</font>" << "red text" << (FormatList() << Format(0, 0, 8));
-     QTest::newRow("font size") << "<font size=\"1\">text</font>" << "text" << (FormatList() << Format(0, 0, 4));
-     QTest::newRow("font empty") << "<font>text</font>" << "text" << FormatList();
-     QTest::newRow("font bad 1") << "<font ezis=\"blah\">text</font>" << "text" << FormatList();
-     QTest::newRow("font bad 2") << "<font size=\"1>text</font>" << "" << FormatList();
-     QTest::newRow("extra close") << "<b>text</b></b>" << "text" << (FormatList() << Format(Format::Bold, 0, 4));
-     QTest::newRow("extra space") << "<b >text</b>" << "text" << (FormatList() << Format(Format::Bold, 0, 4));
-     QTest::newRow("entities") << "&lt;b&gt;this &amp; that&lt;/b&gt;" << "<b>this & that</b>" << FormatList();
-     QTest::newRow("newline") << "text<br>more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList();
-     QTest::newRow("paragraph") << "text<p>more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList();
-     QTest::newRow("paragraph closed") << "text<p>more text</p>more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text")  + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList();
-     QTest::newRow("paragraph closed bold") << "<b>text<p>more text</p>more text</b>" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text")  + QChar(QChar::LineSeparator) + QLatin1String("more text") << (FormatList() << Format(Format::Bold, 0, 24));
-     QTest::newRow("self-closing newline") << "text<br/>more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList();
-     QTest::newRow("empty") << "" << "" << FormatList();
-     QTest::newRow("unknown tag") << "<a href='#'><foo>underline</foo></a> not" << "underline not" << (FormatList() << Format(Format::Underline, 0, 9));
-     QTest::newRow("ordered list") << "<ol><li>one<li>two" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") << FormatList();
-     QTest::newRow("ordered list closed") << "<ol><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList();
-     QTest::newRow("ordered list alpha") << "<ol type=\"a\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("a.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("b.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList();
-     QTest::newRow("ordered list upper alpha") << "<ol type=\"A\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("A.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("B.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList();
-     QTest::newRow("ordered list roman") << "<ol type=\"i\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("i.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("ii.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList();
-     QTest::newRow("ordered list upper roman") << "<ol type=\"I\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("I.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("II.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList();
-     QTest::newRow("ordered list bad") << "<ol type=\"z\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList();
-     QTest::newRow("unordered list") << "<ul><li>one<li>two" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") << FormatList();
-     QTest::newRow("unordered list closed") << "<ul><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList();
-     QTest::newRow("unordered list disc") << "<ul type=\"disc\"><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + disc + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + disc + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList();
-     QTest::newRow("unordered list square") << "<ul type=\"square\"><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + square + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + square + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList();
-     QTest::newRow("unordered list bad") << "<ul type=\"bad\"><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList();
-     QTest::newRow("header close") << "<h1>head</h1>more" << QChar(QChar::LineSeparator) + QLatin1String("head") + QChar(QChar::LineSeparator) + QLatin1String("more") << (FormatList() << Format(Format::Bold, 0, 5));
-     QTest::newRow("h0") << "<h0>head" << "head" << FormatList();
-     QTest::newRow("h1") << "<h1>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5));
-     QTest::newRow("h2") << "<h2>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5));
-     QTest::newRow("h3") << "<h3>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5));
-     QTest::newRow("h4") << "<h4>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5));
-     QTest::newRow("h5") << "<h5>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5));
-     QTest::newRow("h6") << "<h6>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5));
-     QTest::newRow("h7") << "<h7>head" << "head" << FormatList();
-     QTest::newRow("pre") << "normal<pre>pre text</pre>normal" << QLatin1String("normal") + QChar(QChar::LineSeparator) + QLatin1String("pre") + QChar(QChar::Nbsp) + QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("normal") << (FormatList() << Format(0, 6, 9));
-     QTest::newRow("pre lb") << "normal<pre>pre\n text</pre>normal" << QLatin1String("normal") + QChar(QChar::LineSeparator) + QLatin1String("pre") + QChar(QChar::LineSeparator) + QChar(QChar::Nbsp) + QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("normal") << (FormatList() << Format(0, 6, 10));
-     QTest::newRow("line feed") << "line\nfeed" << "line feed" << FormatList();
-     QTest::newRow("leading whitespace") << " leading whitespace" << "leading whitespace" << FormatList();
-     QTest::newRow("trailing whitespace") << "trailing whitespace " << "trailing whitespace" << FormatList();
-     QTest::newRow("consecutive whitespace") << " consecutive  \t \n  whitespace" << "consecutive whitespace" << FormatList();
-     QTest::newRow("space after newline") << "text<br/> more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList();
-     QTest::newRow("space after paragraph") << "text<p> more text</p> more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList();
-     QTest::newRow("space in header") << "<h1> head</h1> " << QChar(QChar::LineSeparator) + QLatin1String("head") + QChar(QChar::LineSeparator) << (FormatList() << Format(Format::Bold, 0, 5));
-     QTest::newRow("space before bold") << "this is <b>bold</b>" << "this is bold" << (FormatList() << Format(Format::Bold, 8, 4));
-     QTest::newRow("space leading bold") << "this is<b> bold</b>" << "this is bold" << (FormatList() << Format(Format::Bold, 7, 5));
-     QTest::newRow("space trailing bold") << "this is <b>bold </b>" << "this is bold " << (FormatList() << Format(Format::Bold, 8, 5));
-     QTest::newRow("img") << "a<img src=\"blah.png\"/>b" << "a  b" << FormatList();
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <qtest.h>
 +#include <QtTest/QtTest>
 +#include <QtGui/QTextLayout>
 +#include <QtCore/QList>
 +#include <QtQuick/private/qquickstyledtext_p.h>
 +
 +class tst_qquickstyledtext : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    tst_qquickstyledtext()
 +    {
 +    }
 +
 +    struct Format {
 +        enum Type {
 +            Bold = 0x01,
 +            Underline = 0x02,
 +            Italic = 0x04
 +        };
 +        Format(int t, int s, int l)
 +            : type(t), start(s), length(l) {}
 +        int type;
 +        int start;
 +        int length;
 +    };
 +    typedef QList<Format> FormatList;
 +
 +    static const QChar bullet;
 +    static const QChar disc;
 +    static const QChar square;
 +
 +private slots:
 +    void textOutput();
 +    void textOutput_data();
 +};
 +
 +Q_DECLARE_METATYPE(tst_qquickstyledtext::FormatList);
 +
 +const QChar tst_qquickstyledtext::bullet(0x2022);
 +const QChar tst_qquickstyledtext::disc(0x25e6);
 +const QChar tst_qquickstyledtext::square(0x25a1);
 +
 +// For malformed input all we test is that we get the expected text and format out.
 +// 
 +void tst_qquickstyledtext::textOutput_data()
 +{
 +    QTest::addColumn<QString>("input");
 +    QTest::addColumn<QString>("output");
 +    QTest::addColumn<FormatList>("formats");
-     QQuickStyledText::parse(input, layout, imgTags, QUrl(), 0, false);
++    QTest::addColumn<bool>("modifiesFontSize");
++
++    QTest::newRow("bold") << "<b>bold</b>" << "bold" << (FormatList() << Format(Format::Bold, 0, 4)) << false;
++    QTest::newRow("italic") << "<i>italic</i>" << "italic" << (FormatList() << Format(Format::Italic, 0, 6)) << false;
++    QTest::newRow("underline") << "<u>underline</u>" << "underline" << (FormatList() << Format(Format::Underline, 0, 9)) << false;
++    QTest::newRow("strong") << "<strong>strong</strong>" << "strong" << (FormatList() << Format(Format::Bold, 0, 6)) << false;
++    QTest::newRow("underline") << "<u>underline</u>" << "underline" << (FormatList() << Format(Format::Underline, 0, 9)) << false;
++    QTest::newRow("missing >") << "<b>text</b" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false;
++    QTest::newRow("missing b>") << "<b>text</" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false;
++    QTest::newRow("missing /b>") << "<b>text<" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false;
++    QTest::newRow("missing </b>") << "<b>text" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false;
++    QTest::newRow("nested") << "<b>text <i>italic</i> bold</b>" << "text italic bold" << (FormatList() << Format(Format::Bold, 0, 5) << Format(Format::Bold | Format::Italic, 5, 6) << Format(Format::Bold, 11, 5)) << false;
++    QTest::newRow("bad nest") << "<b>text <i>italic</b></i>" << "text italic" << (FormatList() << Format(Format::Bold, 0, 5) << Format(Format::Bold | Format::Italic, 5, 6)) << false;
++    QTest::newRow("font color") << "<font color=\"red\">red text</font>" << "red text" << (FormatList() << Format(0, 0, 8)) << false;
++    QTest::newRow("font color: single quote") << "<font color='red'>red text</font>" << "red text" << (FormatList() << Format(0, 0, 8)) << false;
++    QTest::newRow("font size") << "<font size=\"1\">text</font>" << "text" << (FormatList() << Format(0, 0, 4)) << true;
++    QTest::newRow("font empty") << "<font>text</font>" << "text" << FormatList() << false;
++    QTest::newRow("font bad 1") << "<font ezis=\"blah\">text</font>" << "text" << FormatList() << false;
++    QTest::newRow("font bad 2") << "<font size=\"1>text</font>" << "" << FormatList() << false;
++    QTest::newRow("extra close") << "<b>text</b></b>" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false;
++    QTest::newRow("extra space") << "<b >text</b>" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false;
++    QTest::newRow("entities") << "&lt;b&gt;this &amp; that&lt;/b&gt;" << "<b>this & that</b>" << FormatList() << false;
++    QTest::newRow("newline") << "text<br>more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList() << false;
++    QTest::newRow("paragraph") << "text<p>more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList() << false;
++    QTest::newRow("paragraph closed") << "text<p>more text</p>more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text")  + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList() << false;
++    QTest::newRow("paragraph closed bold") << "<b>text<p>more text</p>more text</b>" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text")  + QChar(QChar::LineSeparator) + QLatin1String("more text") << (FormatList() << Format(Format::Bold, 0, 24)) << false;
++    QTest::newRow("self-closing newline") << "text<br/>more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList() << false;
++    QTest::newRow("empty") << "" << "" << FormatList() << false;
++    QTest::newRow("unknown tag") << "<a href='#'><foo>underline</foo></a> not" << "underline not" << (FormatList() << Format(Format::Underline, 0, 9)) << false;
++    QTest::newRow("ordered list") << "<ol><li>one<li>two" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") << FormatList() << false;
++    QTest::newRow("ordered list closed") << "<ol><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false;
++    QTest::newRow("ordered list alpha") << "<ol type=\"a\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("a.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("b.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false;
++    QTest::newRow("ordered list upper alpha") << "<ol type=\"A\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("A.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("B.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false;
++    QTest::newRow("ordered list roman") << "<ol type=\"i\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("i.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("ii.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false;
++    QTest::newRow("ordered list upper roman") << "<ol type=\"I\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("I.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("II.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false;
++    QTest::newRow("ordered list bad") << "<ol type=\"z\"><li>one</li><li>two</li></ol>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("1.") + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + QLatin1String("2.") + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false;
++    QTest::newRow("unordered list") << "<ul><li>one<li>two" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") << FormatList() << false;
++    QTest::newRow("unordered list closed") << "<ul><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false;
++    QTest::newRow("unordered list disc") << "<ul type=\"disc\"><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + disc + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + disc + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false;
++    QTest::newRow("unordered list square") << "<ul type=\"square\"><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + square + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + square + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false;
++    QTest::newRow("unordered list bad") << "<ul type=\"bad\"><li>one</li><li>two</li></ul>" << QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("one") + QChar(QChar::LineSeparator) + QString(6, QChar::Nbsp) + bullet + QString(2, QChar::Nbsp) + QLatin1String("two") + QChar(QChar::LineSeparator) << FormatList() << false;
++    QTest::newRow("header close") << "<h1>head</h1>more" << QChar(QChar::LineSeparator) + QLatin1String("head") + QChar(QChar::LineSeparator) + QLatin1String("more") << (FormatList() << Format(Format::Bold, 0, 5)) << true;
++    QTest::newRow("h0") << "<h0>head" << "head" << FormatList() << false;
++    QTest::newRow("h1") << "<h1>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true;
++    QTest::newRow("h2") << "<h2>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true;
++    QTest::newRow("h3") << "<h3>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true;
++    QTest::newRow("h4") << "<h4>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true;
++    QTest::newRow("h5") << "<h5>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true;
++    QTest::newRow("h6") << "<h6>head" << QChar(QChar::LineSeparator) + QLatin1String("head") << (FormatList() << Format(Format::Bold, 0, 5)) << true;
++    QTest::newRow("h7") << "<h7>head" << "head" << FormatList() << false;
++    QTest::newRow("pre") << "normal<pre>pre text</pre>normal" << QLatin1String("normal") + QChar(QChar::LineSeparator) + QLatin1String("pre") + QChar(QChar::Nbsp) + QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("normal") << (FormatList() << Format(0, 6, 9)) << false;
++    QTest::newRow("pre lb") << "normal<pre>pre\n text</pre>normal" << QLatin1String("normal") + QChar(QChar::LineSeparator) + QLatin1String("pre") + QChar(QChar::LineSeparator) + QChar(QChar::Nbsp) + QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("normal") << (FormatList() << Format(0, 6, 10)) << false;
++    QTest::newRow("line feed") << "line\nfeed" << "line feed" << FormatList() << false;
++    QTest::newRow("leading whitespace") << " leading whitespace" << "leading whitespace" << FormatList() << false;
++    QTest::newRow("trailing whitespace") << "trailing whitespace " << "trailing whitespace" << FormatList() << false;
++    QTest::newRow("consecutive whitespace") << " consecutive  \t \n  whitespace" << "consecutive whitespace" << FormatList() << false;
++    QTest::newRow("space after newline") << "text<br/> more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList() << false;
++    QTest::newRow("space after paragraph") << "text<p> more text</p> more text" << QLatin1String("text") + QChar(QChar::LineSeparator) + QLatin1String("more text") + QChar(QChar::LineSeparator) + QLatin1String("more text") << FormatList() << false;
++    QTest::newRow("space in header") << "<h1> head</h1> " << QChar(QChar::LineSeparator) + QLatin1String("head") + QChar(QChar::LineSeparator) << (FormatList() << Format(Format::Bold, 0, 5)) << true;
++    QTest::newRow("space before bold") << "this is <b>bold</b>" << "this is bold" << (FormatList() << Format(Format::Bold, 8, 4)) << false;
++    QTest::newRow("space leading bold") << "this is<b> bold</b>" << "this is bold" << (FormatList() << Format(Format::Bold, 7, 5)) << false;
++    QTest::newRow("space trailing bold") << "this is <b>bold </b>" << "this is bold " << (FormatList() << Format(Format::Bold, 8, 5)) << false;
++    QTest::newRow("img") << "a<img src=\"blah.png\"/>b" << "a  b" << FormatList() << false;
 +}
 +
 +void tst_qquickstyledtext::textOutput()
 +{
 +    QFETCH(QString, input);
 +    QFETCH(QString, output);
 +    QFETCH(FormatList, formats);
++    QFETCH(bool, modifiesFontSize);
 +
 +    QTextLayout layout;
 +    QList<QQuickStyledTextImgTag*> imgTags;
++    bool fontSizeModified = false;
++    QQuickStyledText::parse(input, layout, imgTags, QUrl(), 0, false, &fontSizeModified);
 +
 +    QCOMPARE(layout.text(), output);
 +
 +    QList<QTextLayout::FormatRange> layoutFormats = layout.additionalFormats();
 +
 +    QCOMPARE(layoutFormats.count(), formats.count());
 +    for (int i = 0; i < formats.count(); ++i) {
 +        QCOMPARE(layoutFormats.at(i).start, formats.at(i).start);
 +        QCOMPARE(layoutFormats.at(i).length, formats.at(i).length);
 +        if (formats.at(i).type & Format::Bold)
 +            QVERIFY(layoutFormats.at(i).format.fontWeight() == QFont::Bold);
 +        else
 +            QVERIFY(layoutFormats.at(i).format.fontWeight() == QFont::Normal);
 +        QVERIFY(layoutFormats.at(i).format.fontItalic() == bool(formats.at(i).type & Format::Italic));
 +        QVERIFY(layoutFormats.at(i).format.fontUnderline() == bool(formats.at(i).type & Format::Underline));
 +    }
++    QCOMPARE(fontSizeModified, modifiesFontSize);
 +}
 +
 +
 +QTEST_MAIN(tst_qquickstyledtext)
 +
 +#include "tst_qquickstyledtext.moc"
index 754395d,0000000..54b5a04
mode 100644,000000..100644
--- /dev/null
@@@ -1,2432 -1,0 +1,2484 @@@
-             metricWidth = qCeil(layout.boundingRect().width());
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <qtest.h>
 +#include <QtTest/QSignalSpy>
 +#include <QTextDocument>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtQuick/private/qquicktext_p.h>
 +#include <private/qquicktext_p_p.h>
 +#include <private/qqmlvaluetype_p.h>
 +#include <QFontMetrics>
 +#include <QGraphicsSceneMouseEvent>
 +#include <qmath.h>
 +#include <QtQuick/QQuickView>
 +#include <private/qapplication_p.h>
 +#include <limits.h>
 +#include <QtGui/QMouseEvent>
 +#include "../../shared/util.h"
 +#include "testhttpserver.h"
 +
 +DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
 +
++Q_DECLARE_METATYPE(QQuickText::TextFormat)
++
 +class tst_qquicktext : public QQmlDataTest
 +{
 +    Q_OBJECT
 +public:
 +    tst_qquicktext();
 +
 +private slots:
 +    void text();
 +    void width();
 +    void wrap();
 +    void elide();
++    void multilineElide_data();
 +    void multilineElide();
 +    void textFormat();
 +
 +    void alignments_data();
 +    void alignments();
 +
 +    void baseUrl();
 +    void embeddedImages_data();
 +    void embeddedImages();
 +
 +    void lineCount();
 +    void lineHeight();
 +
 +    // ### these tests may be trivial
 +    void horizontalAlignment();
 +    void horizontalAlignment_RightToLeft();
 +    void verticalAlignment();
 +    void font();
 +    void style();
 +    void color();
 +    void smooth();
 +
 +    // QQmlFontValueType
 +    void weight();
 +    void underline();
 +    void overline();
 +    void strikeout();
 +    void capitalization();
 +    void letterSpacing();
 +    void wordSpacing();
 +
 +    void clickLink();
 +
 +    void implicitSize_data();
 +    void implicitSize();
 +    void contentSize();
 +
 +    void lineLaidOut();
 +
 +    void imgTagsBaseUrl_data();
 +    void imgTagsBaseUrl();
 +    void imgTagsAlign_data();
 +    void imgTagsAlign();
 +    void imgTagsMultipleImages();
 +    void imgTagsElide();
 +    void imgTagsUpdates();
 +    void imgTagsError();
 +    void fontSizeMode_data();
 +    void fontSizeMode();
 +    void fontSizeModeMultiline_data();
 +    void fontSizeModeMultiline();
 +    void multilengthStrings_data();
 +    void multilengthStrings();
++    void fontFormatSizes_data();
++    void fontFormatSizes();
 +
 +private:
 +    QStringList standard;
 +    QStringList richText;
 +
 +    QStringList horizontalAlignmentmentStrings;
 +    QStringList verticalAlignmentmentStrings;
 +
 +    QList<Qt::Alignment> verticalAlignmentments;
 +    QList<Qt::Alignment> horizontalAlignmentments;
 +
 +    QStringList styleStrings;
 +    QList<QQuickText::TextStyle> styles;
 +
 +    QStringList colorStrings;
 +
 +    QQmlEngine engine;
 +
 +    QQuickView *createView(const QString &filename);
 +};
 +
 +tst_qquicktext::tst_qquicktext()
 +{
 +    standard << "the quick brown fox jumped over the lazy dog"
 +            << "the quick brown fox\n jumped over the lazy dog";
 +
 +    richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
 +            << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
 +
 +    horizontalAlignmentmentStrings << "AlignLeft"
 +            << "AlignRight"
 +            << "AlignHCenter";
 +
 +    verticalAlignmentmentStrings << "AlignTop"
 +            << "AlignBottom"
 +            << "AlignVCenter";
 +
 +    horizontalAlignmentments << Qt::AlignLeft
 +            << Qt::AlignRight
 +            << Qt::AlignHCenter;
 +
 +    verticalAlignmentments << Qt::AlignTop
 +            << Qt::AlignBottom
 +            << Qt::AlignVCenter;
 +
 +    styleStrings << "Normal"
 +            << "Outline"
 +            << "Raised"
 +            << "Sunken";
 +
 +    styles << QQuickText::Normal
 +            << QQuickText::Outline
 +            << QQuickText::Raised
 +            << QQuickText::Sunken;
 +
 +    colorStrings << "aliceblue"
 +            << "antiquewhite"
 +            << "aqua"
 +            << "darkkhaki"
 +            << "darkolivegreen"
 +            << "dimgray"
 +            << "palevioletred"
 +            << "lightsteelblue"
 +            << "#000000"
 +            << "#AAAAAA"
 +            << "#FFFFFF"
 +            << "#2AC05F";
 +    //
 +    // need a different test to do alpha channel test
 +    // << "#AA0011DD"
 +    // << "#00F16B11";
 +    //
 +}
 +
 +QQuickView *tst_qquicktext::createView(const QString &filename)
 +{
 +    QQuickView *canvas = new QQuickView(0);
 +
 +    canvas->setSource(QUrl::fromLocalFile(filename));
 +    return canvas;
 +}
 +
 +void tst_qquicktext::text()
 +{
 +    {
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->text(), QString(""));
 +        QVERIFY(textObject->width() == 0);
 +
 +        delete textObject;
 +    }
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->text(), standard.at(i));
 +        QVERIFY(textObject->width() > 0);
 +
 +        delete textObject;
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QString expected = richText.at(i);
 +        QCOMPARE(textObject->text(), expected.replace("\\\"", "\""));
 +        QVERIFY(textObject->width() > 0);
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::width()
 +{
 +    // uses Font metrics to find the width for standard and document to find the width for rich
 +    {
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData("import QtQuick 2.0\nText { text: \"\" }", QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->width(), 0.);
 +
 +        delete textObject;
 +    }
 +
 +    bool requiresUnhintedMetrics = !qmlDisableDistanceField();
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        QVERIFY(!Qt::mightBeRichText(standard.at(i))); // self-test
 +
 +        QFont f;
 +        qreal metricWidth = 0.0;
 +
 +        if (requiresUnhintedMetrics) {
 +            QString s = standard.at(i);
 +            s.replace(QLatin1Char('\n'), QChar::LineSeparator);
 +
 +            QTextLayout layout(s);
 +            layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
 +            {
 +                QTextOption option;
 +                option.setUseDesignMetrics(true);
 +                layout.setTextOption(option);
 +            }
 +
 +            layout.beginLayout();
 +            forever {
 +                QTextLine line = layout.createLine();
 +                if (!line.isValid())
 +                    break;
 +            }
 +
 +            layout.endLayout();
 +
-             qreal metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
-             metricWidth = qCeil(metricWidth);
++            metricWidth = layout.boundingRect().width();
 +        } else {
 +            QFontMetricsF fm(f);
-         QTextDocument *doc = textPrivate->textDocument();
++            metricWidth = fm.size(Qt::TextExpandTabs && Qt::TextShowMnemonic, standard.at(i)).width();
 +        }
 +
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QVERIFY(textObject->boundingRect().width() > 0);
 +        QCOMPARE(textObject->width(), qreal(metricWidth));
 +        QVERIFY(textObject->textFormat() == QQuickText::AutoText); // setting text doesn't change format
 +
 +        delete textObject;
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        QVERIFY(Qt::mightBeRichText(richText.at(i))); // self-test
 +
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\"; textFormat: Text.RichText }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +        QVERIFY(textObject != 0);
 +
 +        QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
 +        QVERIFY(textPrivate != 0);
++        QVERIFY(textPrivate->extra.isAllocated());
 +
-         // richtext - does nothing
++        QTextDocument *doc = textPrivate->extra->doc;
 +        QVERIFY(doc != 0);
 +
 +        QCOMPARE(int(textObject->width()), int(doc->idealWidth()));
 +        QVERIFY(textObject->textFormat() == QQuickText::RichText);
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::wrap()
 +{
 +    int textHeight = 0;
 +    // for specified width and wrap set true
 +    {
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; wrapMode: Text.WordWrap; width: 300 }", QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +        textHeight = textObject->height();
 +
 +        QVERIFY(textObject != 0);
 +        QVERIFY(textObject->wrapMode() == QQuickText::WordWrap);
 +        QCOMPARE(textObject->width(), 300.);
 +
 +        delete textObject;
 +    }
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->width(), 30.);
 +        QVERIFY(textObject->height() > textHeight);
 +
 +        int oldHeight = textObject->height();
 +        textObject->setWidth(100);
 +        QVERIFY(textObject->height() < oldHeight);
 +
 +        delete textObject;
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; text: \"" + richText.at(i) + "\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->width(), 30.);
 +        QVERIFY(textObject->height() > textHeight);
 +
 +        qreal oldHeight = textObject->height();
 +        textObject->setWidth(100);
 +        QVERIFY(textObject->height() < oldHeight);
 +
 +        delete textObject;
 +    }
 +
 +    // richtext again with a fixed height
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; width: 30; height: 50; text: \"" + richText.at(i) + "\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->width(), 30.);
 +        QVERIFY(textObject->implicitHeight() > textHeight);
 +
 +        qreal oldHeight = textObject->implicitHeight();
 +        textObject->setWidth(100);
 +        QVERIFY(textObject->implicitHeight() < oldHeight);
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::elide()
 +{
 +    for (QQuickText::TextElideMode m = QQuickText::ElideLeft; m<=QQuickText::ElideNone; m=QQuickText::TextElideMode(int(m)+1)) {
 +        const char* elidename[]={"ElideLeft", "ElideRight", "ElideMiddle", "ElideNone"};
 +        QString elide = "elide: Text." + QString(elidename[int(m)]) + ";";
 +
 +        // XXX Poor coverage.
 +
 +        {
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(("import QtQuick 2.0\nText { text: \"\"; "+elide+" width: 100 }").toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +            QCOMPARE(textObject->elideMode(), m);
 +            QCOMPARE(textObject->width(), 100.);
 +
 +            delete textObject;
 +        }
 +
 +        for (int i = 0; i < standard.size(); i++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + standard.at(i) + "\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +            QCOMPARE(textObject->elideMode(), m);
 +            QCOMPARE(textObject->width(), 100.);
 +
++            if (m != QQuickText::ElideNone && !standard.at(i).contains('\n'))
++                QVERIFY(textObject->contentWidth() <= textObject->width());
++
 +            delete textObject;
 +        }
 +
-     QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft);
 +        for (int i = 0; i < richText.size(); i++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { "+elide+" width: 100; text: \"" + richText.at(i) + "\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +            QCOMPARE(textObject->elideMode(), m);
 +            QCOMPARE(textObject->width(), 100.);
 +
++            if (m != QQuickText::ElideNone && standard.at(i).contains("<br>"))
++                QVERIFY(textObject->contentWidth() <= textObject->width());
++
 +            delete textObject;
 +        }
 +    }
 +}
 +
++void tst_qquicktext::multilineElide_data()
++{
++    QTest::addColumn<QQuickText::TextFormat>("format");
++    QTest::newRow("plain") << QQuickText::PlainText;
++    QTest::newRow("styled") << QQuickText::StyledText;
++}
++
 +void tst_qquicktext::multilineElide()
 +{
++    QFETCH(QQuickText::TextFormat, format);
 +    QQuickView *canvas = createView(testFile("multilineelide.qml"));
 +
 +    QQuickText *myText = qobject_cast<QQuickText*>(canvas->rootObject());
 +    QVERIFY(myText != 0);
++    myText->setTextFormat(format);
 +
 +    QCOMPARE(myText->lineCount(), 3);
 +    QCOMPARE(myText->truncated(), true);
 +
 +    qreal lineHeight = myText->contentHeight() / 3.;
 +
++    // Set a valid height greater than the truncated content height and ensure the line count is
++    // unchanged.
++    myText->setHeight(200);
++    QCOMPARE(myText->lineCount(), 3);
++    QCOMPARE(myText->truncated(), true);
++
 +    // reduce size and ensure fewer lines are drawn
 +    myText->setHeight(lineHeight * 2);
 +    QCOMPARE(myText->lineCount(), 2);
 +
 +    myText->setHeight(lineHeight);
 +    QCOMPARE(myText->lineCount(), 1);
 +
 +    myText->setHeight(5);
 +    QCOMPARE(myText->lineCount(), 1);
 +
 +    myText->setHeight(lineHeight * 3);
 +    QCOMPARE(myText->lineCount(), 3);
 +
 +    // remove max count and show all lines.
 +    myText->setHeight(1000);
 +    myText->resetMaximumLineCount();
 +
 +    QCOMPARE(myText->truncated(), false);
 +
 +    // reduce size again
 +    myText->setHeight(lineHeight * 2);
 +    QCOMPARE(myText->lineCount(), 2);
 +    QCOMPARE(myText->truncated(), true);
 +
 +    // change line height
 +    myText->setLineHeight(1.1);
 +    QCOMPARE(myText->lineCount(), 1);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquicktext::textFormat()
 +{
 +    {
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData("import QtQuick 2.0\nText { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QVERIFY(textObject->textFormat() == QQuickText::RichText);
 +
 +        QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
 +        QVERIFY(textPrivate != 0);
 +        QVERIFY(textPrivate->richText == true);
 +
 +        delete textObject;
 +    }
 +    {
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\" }", QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QVERIFY(textObject->textFormat() == QQuickText::AutoText);
 +
 +        QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
 +        QVERIFY(textPrivate != 0);
 +        QVERIFY(textPrivate->styledText == true);
 +
 +        delete textObject;
 +    }
 +    {
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData("import QtQuick 2.0\nText { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QVERIFY(textObject->textFormat() == QQuickText::PlainText);
 +
 +        delete textObject;
 +    }
 +}
 +
 +
 +void tst_qquicktext::alignments_data()
 +{
 +    QTest::addColumn<int>("hAlign");
 +    QTest::addColumn<int>("vAlign");
 +    QTest::addColumn<QString>("expectfile");
 +
 +    QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << testFile("alignments_lt.png");
 +    QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << testFile("alignments_rt.png");
 +    QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << testFile("alignments_ct.png");
 +
 +    QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << testFile("alignments_lb.png");
 +    QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << testFile("alignments_rb.png");
 +    QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << testFile("alignments_cb.png");
 +
 +    QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << testFile("alignments_lc.png");
 +    QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << testFile("alignments_rc.png");
 +    QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << testFile("alignments_cc.png");
 +}
 +
 +
 +void tst_qquicktext::alignments()
 +{
 +    QSKIP("Text alignment pixmap comparison tests will not work with scenegraph");
 +#if (0)// No widgets in scenegraph
 +    QFETCH(int, hAlign);
 +    QFETCH(int, vAlign);
 +    QFETCH(QString, expectfile);
 +
 +    QQuickView *canvas = createView(testFile("alignments.qml"));
 +    canvas->show();
 +    canvas->requestActivateWindow();
 +    QTest::qWait(50);
 +    QTRY_COMPARE(QGuiApplication::activeWindow(), static_cast<QWidget *>(canvas));
 +
 +    QObject *ob = canvas->rootObject();
 +    QVERIFY(ob != 0);
 +    ob->setProperty("horizontalAlignment",hAlign);
 +    ob->setProperty("verticalAlignment",vAlign);
 +    QTRY_COMPARE(ob->property("running").toBool(),false);
 +    QImage actual(canvas->width(), canvas->height(), QImage::Format_RGB32);
 +    actual.fill(qRgb(255,255,255));
 +    QPainter p(&actual);
 +    canvas->render(&p);
 +
 +    QImage expect(expectfile);
 +    if (QGuiApplicationPrivate::graphics_system_name == "raster" || QGuiApplicationPrivate::graphics_system_name == "") {
 +        QCOMPARE(actual,expect);
 +    }
 +    delete canvas;
 +#endif
 +}
 +
 +//the alignment tests may be trivial o.oa
 +void tst_qquicktext::horizontalAlignment()
 +{
 +    //test one align each, and then test if two align fails.
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +            QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
 +
 +            delete textObject;
 +        }
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        for (int j=0; j < horizontalAlignmentmentStrings.size(); j++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { horizontalAlignment: \"" + horizontalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +            QCOMPARE((int)textObject->hAlign(), (int)horizontalAlignmentments.at(j));
 +
 +            delete textObject;
 +        }
 +    }
 +
 +}
 +
 +void tst_qquicktext::horizontalAlignment_RightToLeft()
 +{
 +    QQuickView *canvas = createView(testFile("horizontalAlignment_RightToLeft.qml"));
 +    QQuickText *text = canvas->rootObject()->findChild<QQuickText*>("text");
 +    QVERIFY(text != 0);
 +    canvas->show();
 +
 +    QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(text);
 +    QVERIFY(textPrivate != 0);
 +
 +    QTRY_VERIFY(textPrivate->layout.lineCount());
 +
 +    // implicit alignment should follow the reading direction of RTL text
 +    QCOMPARE(text->hAlign(), QQuickText::AlignRight);
 +    QCOMPARE(text->effectiveHAlign(), text->hAlign());
 +    QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
 +
 +    // explicitly left aligned text
 +    text->setHAlign(QQuickText::AlignLeft);
 +    QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
 +    QCOMPARE(text->effectiveHAlign(), text->hAlign());
 +    QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
 +
 +    // explicitly right aligned text
 +    text->setHAlign(QQuickText::AlignRight);
 +    QCOMPARE(text->hAlign(), QQuickText::AlignRight);
 +    QCOMPARE(text->effectiveHAlign(), text->hAlign());
 +    QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
 +
 +    // change to rich text
 +    QString textString = text->text();
 +    text->setText(QString("<i>") + textString + QString("</i>"));
 +    text->setTextFormat(QQuickText::RichText);
 +    text->resetHAlign();
 +
 +    // implicitly aligned rich text should follow the reading direction of text
 +    QCOMPARE(text->hAlign(), QQuickText::AlignRight);
 +    QCOMPARE(text->effectiveHAlign(), text->hAlign());
-     QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignRight);
++    QVERIFY(textPrivate->extra.isAllocated());
++    QVERIFY(textPrivate->extra->doc->defaultTextOption().alignment() & Qt::AlignLeft);
 +
 +    // explicitly left aligned rich text
 +    text->setHAlign(QQuickText::AlignLeft);
 +    QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
 +    QCOMPARE(text->effectiveHAlign(), text->hAlign());
-     QVERIFY(textPrivate->textDocument()->defaultTextOption().alignment() & Qt::AlignLeft);
++    QVERIFY(textPrivate->extra->doc->defaultTextOption().alignment() & Qt::AlignRight);
 +
 +    // explicitly right aligned rich text
 +    text->setHAlign(QQuickText::AlignRight);
 +    QCOMPARE(text->hAlign(), QQuickText::AlignRight);
 +    QCOMPARE(text->effectiveHAlign(), text->hAlign());
-     QTextDocument *doc = textPrivate->textDocument();
-     QVERIFY(doc == 0);
++    QVERIFY(textPrivate->extra->doc->defaultTextOption().alignment() & Qt::AlignLeft);
 +
 +    text->setText(textString);
 +    text->setTextFormat(QQuickText::PlainText);
 +
 +    // explicitly center aligned
 +    text->setHAlign(QQuickText::AlignHCenter);
 +    QCOMPARE(text->hAlign(), QQuickText::AlignHCenter);
 +    QCOMPARE(text->effectiveHAlign(), text->hAlign());
 +    QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
 +    QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().right() > canvas->width()/2);
 +
 +    // reseted alignment should go back to following the text reading direction
 +    text->resetHAlign();
 +    QCOMPARE(text->hAlign(), QQuickText::AlignRight);
 +    QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
 +
 +    // mirror the text item
 +    QQuickItemPrivate::get(text)->setLayoutMirror(true);
 +
 +    // mirrored implicit alignment should continue to follow the reading direction of the text
 +    QCOMPARE(text->hAlign(), QQuickText::AlignRight);
 +    QCOMPARE(text->effectiveHAlign(), QQuickText::AlignRight);
 +    QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
 +
 +    // mirrored explicitly right aligned behaves as left aligned
 +    text->setHAlign(QQuickText::AlignRight);
 +    QCOMPARE(text->hAlign(), QQuickText::AlignRight);
 +    QCOMPARE(text->effectiveHAlign(), QQuickText::AlignLeft);
 +    QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
 +
 +    // mirrored explicitly left aligned behaves as right aligned
 +    text->setHAlign(QQuickText::AlignLeft);
 +    QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
 +    QCOMPARE(text->effectiveHAlign(), QQuickText::AlignRight);
 +    QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() > canvas->width()/2);
 +
 +    // disable mirroring
 +    QQuickItemPrivate::get(text)->setLayoutMirror(false);
 +    text->resetHAlign();
 +
 +    // English text should be implicitly left aligned
 +    text->setText("Hello world!");
 +    QCOMPARE(text->hAlign(), QQuickText::AlignLeft);
 +    QVERIFY(textPrivate->layout.lineAt(0).naturalTextRect().left() < canvas->width()/2);
 +
 +    // empty text with implicit alignment follows the system locale-based
 +    // keyboard input direction from QInputMethod::inputDirection()
 +    text->setText("");
 +    QCOMPARE(text->hAlign(), qApp->inputMethod()->inputDirection() == Qt::LeftToRight ?
 +                                  QQuickText::AlignLeft : QQuickText::AlignRight);
 +    text->setHAlign(QQuickText::AlignRight);
 +    QCOMPARE(text->hAlign(), QQuickText::AlignRight);
 +
 +    delete canvas;
 +
 +    // alignment of Text with no text set to it
 +    QString componentStr = "import QtQuick 2.0\nText {}";
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +    QCOMPARE(textObject->hAlign(), qApp->inputMethod()->inputDirection() == Qt::LeftToRight ?
 +                                  QQuickText::AlignLeft : QQuickText::AlignRight);
 +    delete textObject;
 +}
 +
 +void tst_qquicktext::verticalAlignment()
 +{
 +    //test one align each, and then test if two align fails.
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +            QVERIFY(textObject != 0);
 +            QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
 +
 +            delete textObject;
 +        }
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        for (int j=0; j < verticalAlignmentmentStrings.size(); j++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { verticalAlignment: \"" + verticalAlignmentmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +            QVERIFY(textObject != 0);
 +            QCOMPARE((int)textObject->vAlign(), (int)verticalAlignmentments.at(j));
 +
 +            delete textObject;
 +        }
 +    }
 +
 +}
 +
 +void tst_qquicktext::font()
 +{
 +    //test size, then bold, then italic, then family
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { font.pointSize: 40; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE(textObject->font().pointSize(), 40);
 +        QCOMPARE(textObject->font().bold(), false);
 +        QCOMPARE(textObject->font().italic(), false);
 +
 +        delete textObject;
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { font.pixelSize: 40; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE(textObject->font().pixelSize(), 40);
 +        QCOMPARE(textObject->font().bold(), false);
 +        QCOMPARE(textObject->font().italic(), false);
 +
 +        delete textObject;
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { font.bold: true; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE(textObject->font().bold(), true);
 +        QCOMPARE(textObject->font().italic(), false);
 +
 +        delete textObject;
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { font.italic: true; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE(textObject->font().italic(), true);
 +        QCOMPARE(textObject->font().bold(), false);
 +
 +        delete textObject;
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { font.family: \"Helvetica\"; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE(textObject->font().family(), QString("Helvetica"));
 +        QCOMPARE(textObject->font().bold(), false);
 +        QCOMPARE(textObject->font().italic(), false);
 +
 +        delete textObject;
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { font.family: \"\"; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE(textObject->font().family(), QString(""));
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::style()
 +{
 +    //test style
 +    for (int i = 0; i < styles.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { style: \"" + styleStrings.at(i) + "\"; styleColor: \"white\"; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE((int)textObject->style(), (int)styles.at(i));
 +        QCOMPARE(textObject->styleColor(), QColor("white"));
 +
 +        delete textObject;
 +    }
 +    QString componentStr = "import QtQuick 2.0\nText { text: \"Hello World\" }";
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +    QRectF brPre = textObject->boundingRect();
 +    textObject->setStyle(QQuickText::Outline);
 +    QRectF brPost = textObject->boundingRect();
 +
 +    QVERIFY(brPre.width() < brPost.width());
 +    QVERIFY(brPre.height() < brPost.height());
 +
 +    delete textObject;
 +}
 +
 +void tst_qquicktext::color()
 +{
 +    //test style
 +    for (int i = 0; i < colorStrings.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
 +        QCOMPARE(textObject->styleColor(), QColor("black"));
 +        QCOMPARE(textObject->linkColor(), QColor("blue"));
 +
 +        delete textObject;
 +    }
 +
 +    for (int i = 0; i < colorStrings.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { styleColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(i)));
 +        // default color to black?
 +        QCOMPARE(textObject->color(), QColor("black"));
 +        QCOMPARE(textObject->linkColor(), QColor("blue"));
 +
 +        delete textObject;
 +    }
 +
 +    for (int i = 0; i < colorStrings.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { linkColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE(textObject->styleColor(), QColor("black"));
 +        QCOMPARE(textObject->color(), QColor("black"));
 +        QCOMPARE(textObject->linkColor(), QColor(colorStrings.at(i)));
 +
 +        delete textObject;
 +    }
 +
 +    for (int i = 0; i < colorStrings.size(); i++)
 +    {
 +        for (int j = 0; j < colorStrings.size(); j++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { "
 +                    "color: \"" + colorStrings.at(i) + "\"; "
 +                    "styleColor: \"" + colorStrings.at(j) + "\"; "
 +                    "linkColor: \"" + colorStrings.at(j) + "\"; "
 +                    "text: \"Hello World\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +            QCOMPARE(textObject->color(), QColor(colorStrings.at(i)));
 +            QCOMPARE(textObject->styleColor(), QColor(colorStrings.at(j)));
 +            QCOMPARE(textObject->linkColor(), QColor(colorStrings.at(j)));
 +
 +            delete textObject;
 +        }
 +    }
 +    {
 +        QString colorStr = "#AA001234";
 +        QColor testColor("#001234");
 +        testColor.setAlpha(170);
 +
 +        QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QCOMPARE(textObject->color(), testColor);
 +
 +        delete textObject;
 +    } {
 +        QString colorStr = "#001234";
 +        QColor testColor(colorStr);
 +
 +        QString componentStr = "import QtQuick 2.0\nText { color: \"" + colorStr + "\"; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QScopedPointer<QObject> object(textComponent.create());
 +        QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
 +
 +        QSignalSpy spy(textObject, SIGNAL(colorChanged()));
 +
 +        QCOMPARE(textObject->color(), testColor);
 +        textObject->setColor(testColor);
 +        QCOMPARE(textObject->color(), testColor);
 +        QCOMPARE(spy.count(), 0);
 +
 +        testColor = QColor("black");
 +        textObject->setColor(testColor);
 +        QCOMPARE(textObject->color(), testColor);
 +        QCOMPARE(spy.count(), 1);
 +    } {
 +        QString colorStr = "#001234";
 +        QColor testColor(colorStr);
 +
 +        QString componentStr = "import QtQuick 2.0\nText { styleColor: \"" + colorStr + "\"; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QScopedPointer<QObject> object(textComponent.create());
 +        QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
 +
 +        QSignalSpy spy(textObject, SIGNAL(styleColorChanged()));
 +
 +        QCOMPARE(textObject->styleColor(), testColor);
 +        textObject->setStyleColor(testColor);
 +        QCOMPARE(textObject->styleColor(), testColor);
 +        QCOMPARE(spy.count(), 0);
 +
 +        testColor = QColor("black");
 +        textObject->setStyleColor(testColor);
 +        QCOMPARE(textObject->styleColor(), testColor);
 +        QCOMPARE(spy.count(), 1);
 +    } {
 +        QString colorStr = "#001234";
 +        QColor testColor(colorStr);
 +
 +        QString componentStr = "import QtQuick 2.0\nText { linkColor: \"" + colorStr + "\"; text: \"Hello World\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QScopedPointer<QObject> object(textComponent.create());
 +        QQuickText *textObject = qobject_cast<QQuickText*>(object.data());
 +
 +        QSignalSpy spy(textObject, SIGNAL(linkColorChanged()));
 +
 +        QCOMPARE(textObject->linkColor(), testColor);
 +        textObject->setLinkColor(testColor);
 +        QCOMPARE(textObject->linkColor(), testColor);
 +        QCOMPARE(spy.count(), 0);
 +
 +        testColor = QColor("black");
 +        textObject->setLinkColor(testColor);
 +        QCOMPARE(textObject->linkColor(), testColor);
 +        QCOMPARE(spy.count(), 1);
 +    }
 +}
 +
 +void tst_qquicktext::smooth()
 +{
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + standard.at(i) + "\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +            QCOMPARE(textObject->smooth(), true);
 +
 +            delete textObject;
 +        }
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { text: \"" + standard.at(i) + "\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +            QCOMPARE(textObject->smooth(), false);
 +
 +            delete textObject;
 +        }
 +    }
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + richText.at(i) + "\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +            QCOMPARE(textObject->smooth(), true);
 +
 +            delete textObject;
 +        }
 +        {
 +            QString componentStr = "import QtQuick 2.0\nText { text: \"" + richText.at(i) + "\" }";
 +            QQmlComponent textComponent(&engine);
 +            textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +            QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +            QCOMPARE(textObject->smooth(), false);
 +
 +            delete textObject;
 +        }
 +    }
 +}
 +
 +void tst_qquicktext::weight()
 +{
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE((int)textObject->font().weight(), (int)QQmlFontValueType::Normal);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { font.weight: \"Bold\"; text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE((int)textObject->font().weight(), (int)QQmlFontValueType::Bold);
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::underline()
 +{
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().underline(), false);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { font.underline: true; text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().underline(), true);
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::overline()
 +{
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().overline(), false);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { font.overline: true; text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().overline(), true);
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::strikeout()
 +{
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().strikeOut(), false);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { font.strikeout: true; text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().strikeOut(), true);
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::capitalization()
 +{
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE((int)textObject->font().capitalization(), (int)QQmlFontValueType::MixedCase);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllUppercase\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE((int)textObject->font().capitalization(), (int)QQmlFontValueType::AllUppercase);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"AllLowercase\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE((int)textObject->font().capitalization(), (int)QQmlFontValueType::AllLowercase);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"SmallCaps\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE((int)textObject->font().capitalization(), (int)QQmlFontValueType::SmallCaps);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.capitalization: \"Capitalize\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE((int)textObject->font().capitalization(), (int)QQmlFontValueType::Capitalize);
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::letterSpacing()
 +{
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().letterSpacing(), 0.0);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: -2 }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().letterSpacing(), -2.);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.letterSpacing: 3 }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().letterSpacing(), 3.);
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::wordSpacing()
 +{
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().wordSpacing(), 0.0);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: -50 }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().wordSpacing(), -50.);
 +
 +        delete textObject;
 +    }
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.wordSpacing: 200 }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->font().wordSpacing(), 200.);
 +
 +        delete textObject;
 +    }
 +}
 +
 +
 +
 +
 +class EventSender : public QQuickItem
 +{
 +public:
 +    void sendEvent(QMouseEvent *event) {
 +        if (event->type() == QEvent::MouseButtonPress)
 +            mousePressEvent(event);
 +        else if (event->type() == QEvent::MouseButtonRelease)
 +            mouseReleaseEvent(event);
 +        else
 +            qWarning() << "Trying to send unsupported event type";
 +    }
 +};
 +
 +class LinkTest : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    LinkTest() {}
 +
 +    QString link;
 +
 +public slots:
 +    void linkClicked(QString l) { link = l; }
 +};
 +
 +void tst_qquicktext::clickLink()
 +{
 +    {
 +        QString componentStr = "import QtQuick 2.0\nText { text: \"<a href=\\\"http://qt.nokia.com\\\">Hello world!</a>\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +
 +        LinkTest test;
 +        QObject::connect(textObject, SIGNAL(linkActivated(QString)), &test, SLOT(linkClicked(QString)));
 +
 +        {
 +            QMouseEvent me(QEvent::MouseButtonPress,QPointF(textObject->x()/2, textObject->y()/2), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
 +            static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
 +
 +        }
 +
 +        {
 +            QMouseEvent me(QEvent::MouseButtonRelease,QPointF(textObject->x()/2, textObject->y()/2), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
 +            static_cast<EventSender*>(static_cast<QQuickItem*>(textObject))->sendEvent(&me);
 +
 +        }
 +
 +
 +        QCOMPARE(test.link, QLatin1String("http://qt.nokia.com"));
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktext::baseUrl()
 +{
 +    QUrl localUrl("file:///tests/text.qml");
 +    QUrl remoteUrl("http://qt.nokia.com/test.qml");
 +
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData("import QtQuick 2.0\n Text {}", localUrl);
 +    QQuickText *textObject = qobject_cast<QQuickText *>(textComponent.create());
 +
 +    QCOMPARE(textObject->baseUrl(), localUrl);
 +
 +    QSignalSpy spy(textObject, SIGNAL(baseUrlChanged()));
 +
 +    textObject->setBaseUrl(localUrl);
 +    QCOMPARE(textObject->baseUrl(), localUrl);
 +    QCOMPARE(spy.count(), 0);
 +
 +    textObject->setBaseUrl(remoteUrl);
 +    QCOMPARE(textObject->baseUrl(), remoteUrl);
 +    QCOMPARE(spy.count(), 1);
 +
 +    textObject->resetBaseUrl();
 +    QCOMPARE(textObject->baseUrl(), localUrl);
 +    QCOMPARE(spy.count(), 2);
 +}
 +
 +void tst_qquicktext::embeddedImages_data()
 +{
 +    QTest::addColumn<QUrl>("qmlfile");
 +    QTest::addColumn<QString>("error");
 +    QTest::newRow("local") << testFileUrl("embeddedImagesLocal.qml") << "";
 +    QTest::newRow("local-error") << testFileUrl("embeddedImagesLocalError.qml")
 +        << testFileUrl("embeddedImagesLocalError.qml").toString()+":3:1: QML Text: Cannot open: " + testFileUrl("http/notexists.png").toString();
 +    QTest::newRow("local") << testFileUrl("embeddedImagesLocalRelative.qml") << "";
 +    QTest::newRow("remote") << testFileUrl("embeddedImagesRemote.qml") << "";
 +    QTest::newRow("remote-error") << testFileUrl("embeddedImagesRemoteError.qml")
 +        << testFileUrl("embeddedImagesRemoteError.qml").toString()+":3:1: QML Text: Error downloading http://127.0.0.1:14453/notexists.png - server replied: Not found";
 +    QTest::newRow("remote") << testFileUrl("embeddedImagesRemoteRelative.qml") << "";
 +}
 +
 +void tst_qquicktext::embeddedImages()
 +{
 +    // Tests QTBUG-9900
 +
 +    QFETCH(QUrl, qmlfile);
 +    QFETCH(QString, error);
 +
 +    TestHTTPServer server(14453);
 +    server.serveDirectory(testFile("http"));
 +
 +    if (!error.isEmpty())
 +        QTest::ignoreMessage(QtWarningMsg, error.toLatin1());
 +
 +    QQmlComponent textComponent(&engine, qmlfile);
 +    QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +    QVERIFY(textObject != 0);
 +
 +    QTRY_COMPARE(textObject->resourcesLoading(), 0);
 +
 +    QPixmap pm(testFile("http/exists.png"));
 +    if (error.isEmpty()) {
 +        QCOMPARE(textObject->width(), double(pm.width()));
 +        QCOMPARE(textObject->height(), double(pm.height()));
 +    } else {
 +        QVERIFY(16 != pm.width()); // check test is effective
 +        QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon
 +        QCOMPARE(textObject->height(), 16.0);
 +    }
 +
 +    delete textObject;
 +}
 +
 +void tst_qquicktext::lineCount()
 +{
 +    QQuickView *canvas = createView(testFile("lineCount.qml"));
 +
 +    QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
 +    QVERIFY(myText != 0);
 +
 +    QVERIFY(myText->lineCount() > 1);
 +    QVERIFY(!myText->truncated());
 +    QCOMPARE(myText->maximumLineCount(), INT_MAX);
 +
 +    myText->setMaximumLineCount(2);
 +    QCOMPARE(myText->lineCount(), 2);
 +    QCOMPARE(myText->truncated(), true);
 +    QCOMPARE(myText->maximumLineCount(), 2);
 +
 +    myText->resetMaximumLineCount();
 +    QCOMPARE(myText->maximumLineCount(), INT_MAX);
 +    QCOMPARE(myText->truncated(), false);
 +
 +    myText->setElideMode(QQuickText::ElideRight);
 +    myText->setMaximumLineCount(2);
 +    QCOMPARE(myText->lineCount(), 2);
 +    QCOMPARE(myText->truncated(), true);
 +    QCOMPARE(myText->maximumLineCount(), 2);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquicktext::lineHeight()
 +{
 +    QQuickView *canvas = createView(testFile("lineHeight.qml"));
 +
 +    QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
 +    QVERIFY(myText != 0);
 +
 +    QVERIFY(myText->lineHeight() == 1);
 +    QVERIFY(myText->lineHeightMode() == QQuickText::ProportionalHeight);
 +
 +    qreal h = myText->height();
 +    myText->setLineHeight(1.5);
 +    QCOMPARE(myText->height(), qreal(qCeil(h * 1.5)));
 +
 +    myText->setLineHeightMode(QQuickText::FixedHeight);
 +    myText->setLineHeight(20);
 +    QCOMPARE(myText->height(), myText->lineCount() * 20.0);
 +
 +    myText->setText("Lorem ipsum sit <b>amet</b>, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum.");
 +    myText->setLineHeightMode(QQuickText::ProportionalHeight);
 +    myText->setLineHeight(1.0);
 +
 +    qreal h2 = myText->height();
 +    myText->setLineHeight(2.0);
 +    QVERIFY(myText->height() == h2 * 2.0);
 +
 +    myText->setLineHeightMode(QQuickText::FixedHeight);
 +    myText->setLineHeight(10);
 +    QCOMPARE(myText->height(), myText->lineCount() * 10.0);
 +
 +    delete canvas;
 +}
 +
 +void tst_qquicktext::implicitSize_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<QString>("width");
 +    QTest::addColumn<QString>("wrap");
 +    QTest::addColumn<QString>("elide");
 +    QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideNone";
 +    QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone";
 +    QTest::newRow("plain, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideNone";
 +    QTest::newRow("plain, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideRight";
 +    QTest::newRow("plain, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideRight";
 +    QTest::newRow("richtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone";
 +    QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideNone";
 +    QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone";
 +    QTest::newRow("plain_wrap, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideNone";
 +    QTest::newRow("plain_wrap, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideRight";
 +    QTest::newRow("plain_wrap, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideRight";
 +    QTest::newRow("richtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone";
 +}
 +
 +void tst_qquicktext::implicitSize()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(QString, width);
 +    QFETCH(QString, wrap);
 +    QFETCH(QString, elide);
 +    QString componentStr = "import QtQuick 2.0\nText { "
 +            "text: \"" + text + "\"; "
 +            "width: " + width + "; "
 +            "wrapMode: " + wrap + "; "
 +            "elide: " + elide + "; "
 +            "maximumLineCount: 1 }";
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +    QVERIFY(textObject->width() < textObject->implicitWidth());
 +    QVERIFY(textObject->height() == textObject->implicitHeight());
 +
 +    textObject->resetWidth();
 +    QVERIFY(textObject->width() == textObject->implicitWidth());
 +    QVERIFY(textObject->height() == textObject->implicitHeight());
 +
 +    delete textObject;
 +}
 +
 +void tst_qquicktext::contentSize()
 +{
 +    QString componentStr = "import QtQuick 2.0\nText { width: 75; height: 16; font.pixelSize: 10 }";
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QScopedPointer<QObject> object(textComponent.create());
 +    QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
 +
 +    QSignalSpy spy(textObject, SIGNAL(contentSizeChanged()));
 +
 +    textObject->setText("The quick red fox jumped over the lazy brown dog");
 +
 +    QVERIFY(textObject->contentWidth() > textObject->width());
 +    QVERIFY(textObject->contentHeight() < textObject->height());
 +    QCOMPARE(spy.count(), 1);
 +
 +    textObject->setWrapMode(QQuickText::WordWrap);
 +    QVERIFY(textObject->contentWidth() <= textObject->width());
 +    QVERIFY(textObject->contentHeight() > textObject->height());
 +    QCOMPARE(spy.count(), 2);
 +
 +    textObject->setElideMode(QQuickText::ElideRight);
 +    QVERIFY(textObject->contentWidth() <= textObject->width());
 +    QVERIFY(textObject->contentHeight() < textObject->height());
 +    QCOMPARE(spy.count(), 3);
 +    int spyCount = 3;
 +    qreal elidedWidth = textObject->contentWidth();
 +
 +    textObject->setText("The quickredfoxjumpedoverthe lazy brown dog");
 +    QVERIFY(textObject->contentWidth() <= textObject->width());
 +    QVERIFY(textObject->contentHeight() < textObject->height());
 +    // this text probably won't have the same elided width, but it's not guaranteed.
 +    if (textObject->contentWidth() != elidedWidth)
 +        QCOMPARE(spy.count(), ++spyCount);
 +    else
 +        QCOMPARE(spy.count(), spyCount);
 +
 +    textObject->setElideMode(QQuickText::ElideNone);
 +    QVERIFY(textObject->contentWidth() > textObject->width());
 +    QVERIFY(textObject->contentHeight() > textObject->height());
 +    QCOMPARE(spy.count(), ++spyCount);
 +}
 +
 +void tst_qquicktext::lineLaidOut()
 +{
 +    QQuickView *canvas = createView(testFile("lineLayout.qml"));
 +
 +    QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
 +    QVERIFY(myText != 0);
 +
 +    QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
 +    QVERIFY(textPrivate != 0);
 +
-     QTest::addColumn<bool>("canElide");
-     QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << true;
-     QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << false;
++    QVERIFY(!textPrivate->extra.isAllocated());
 +
 +#if defined(Q_OS_MAC)
 +    QVERIFY(myText->lineCount() == textPrivate->linesRects.count());
 +#endif
 +
 +    for (int i = 0; i < textPrivate->layout.lineCount(); ++i) {
 +        QRectF r = textPrivate->layout.lineAt(i).rect();
 +        QVERIFY(r.width() == i * 15);
 +        if (i >= 30)
 +            QVERIFY(r.x() == r.width() + 30);
 +        if (i >= 60) {
 +            QVERIFY(r.x() == r.width() * 2 + 60);
 +            QVERIFY(r.height() == 20);
 +        }
 +    }
 +
 +    delete canvas;
 +}
 +
 +void tst_qquicktext::imgTagsBaseUrl_data()
 +{
 +    QTest::addColumn<QUrl>("src");
 +    QTest::addColumn<QUrl>("baseUrl");
 +    QTest::addColumn<QUrl>("contextUrl");
 +    QTest::addColumn<qreal>("imgHeight");
 +
 +    QTest::newRow("absolute local")
 +            << testFileUrl("images/heart200.png")
 +            << QUrl()
 +            << QUrl()
 +            << 181.;
 +    QTest::newRow("relative local context 1")
 +            << QUrl("images/heart200.png")
 +            << QUrl()
 +            << testFileUrl("/app.qml")
 +            << 181.;
 +    QTest::newRow("relative local context 2")
 +            << QUrl("heart200.png")
 +            << QUrl()
 +            << testFileUrl("images/app.qml")
 +            << 181.;
 +    QTest::newRow("relative local base 1")
 +            << QUrl("images/heart200.png")
 +            << testFileUrl("")
 +            << testFileUrl("nonexistant/app.qml")
 +            << 181.;
 +    QTest::newRow("relative local base 2")
 +            << QUrl("heart200.png")
 +            << testFileUrl("images/")
 +            << testFileUrl("nonexistant/app.qml")
 +            << 181.;
 +    QTest::newRow("base relative to local context")
 +            << QUrl("heart200.png")
 +            << testFileUrl("images/")
 +            << testFileUrl("/app.qml")
 +            << 181.;
 +
 +    QTest::newRow("absolute remote")
 +            << QUrl("http://127.0.0.1:14453/images/heart200.png")
 +            << QUrl()
 +            << QUrl()
 +            << 181.;
 +    QTest::newRow("relative remote base 1")
 +            << QUrl("images/heart200.png")
 +            << QUrl("http://127.0.0.1:14453/")
 +            << testFileUrl("nonexistant/app.qml")
 +            << 181.;
 +    QTest::newRow("relative remote base 2")
 +            << QUrl("heart200.png")
 +            << QUrl("http://127.0.0.1:14453/images/")
 +            << testFileUrl("nonexistant/app.qml")
 +            << 181.;
 +}
 +
 +void tst_qquicktext::imgTagsBaseUrl()
 +{
 +    QFETCH(QUrl, src);
 +    QFETCH(QUrl, baseUrl);
 +    QFETCH(QUrl, contextUrl);
 +    QFETCH(qreal, imgHeight);
 +
 +    TestHTTPServer server(14453);
 +    server.serveDirectory(testFile(""));
 +
 +    QByteArray baseUrlFragment;
 +    if (!baseUrl.isEmpty())
 +        baseUrlFragment = "; baseUrl: \"" + baseUrl.toEncoded() + "\"";
 +    QByteArray componentStr = "import QtQuick 2.0\nText { text: \"This is a test <img src=\\\"" + src.toEncoded() + "\\\">\"" + baseUrlFragment + " }";
 +
 +    QQmlComponent component(&engine);
 +    component.setData(componentStr, contextUrl);
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
 +    QVERIFY(textObject);
 +
 +    QCoreApplication::processEvents();
 +
 +    QTRY_COMPARE(textObject->height(), imgHeight);
 +}
 +
 +void tst_qquicktext::imgTagsAlign_data()
 +{
 +    QTest::addColumn<QString>("src");
 +    QTest::addColumn<int>("imgHeight");
 +    QTest::addColumn<QString>("align");
 +    QTest::newRow("heart-bottom") << "data/images/heart200.png" << 181 <<  "bottom";
 +    QTest::newRow("heart-middle") << "data/images/heart200.png" << 181 <<  "middle";
 +    QTest::newRow("heart-top") << "data/images/heart200.png" << 181 <<  "top";
 +    QTest::newRow("starfish-bottom") << "data/images/starfish_2.png" << 217 <<  "bottom";
 +    QTest::newRow("starfish-middle") << "data/images/starfish_2.png" << 217 <<  "middle";
 +    QTest::newRow("starfish-top") << "data/images/starfish_2.png" << 217 <<  "top";
 +}
 +
 +void tst_qquicktext::imgTagsAlign()
 +{
 +    QFETCH(QString, src);
 +    QFETCH(int, imgHeight);
 +    QFETCH(QString, align);
 +    QString componentStr = "import QtQuick 2.0\nText { text: \"This is a test <img src=\\\"" + src + "\\\" align=\\\"" + align + "\\\"> of image.\" }";
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +    QVERIFY(textObject != 0);
 +    QVERIFY(textObject->height() == imgHeight);
 +
 +    QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
 +    QVERIFY(textPrivate != 0);
 +
 +    QRectF br = textPrivate->layout.boundingRect();
 +    if (align == "bottom")
 +        QVERIFY(br.y() == imgHeight - br.height());
 +    else if (align == "middle")
 +        QVERIFY(br.y() == imgHeight / 2.0 - br.height() / 2.0);
 +    else if (align == "top")
 +        QVERIFY(br.y() == 0);
 +
 +    delete textObject;
 +}
 +
 +void tst_qquicktext::imgTagsMultipleImages()
 +{
 +    QString componentStr = "import QtQuick 2.0\nText { text: \"This is a starfish<img src=\\\"data/images/starfish_2.png\\\" width=\\\"60\\\" height=\\\"60\\\" > and another one<img src=\\\"data/images/heart200.png\\\" width=\\\"85\\\" height=\\\"85\\\">.\" }";
 +
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +    QVERIFY(textObject != 0);
 +    QVERIFY(textObject->height() == 85);
 +
 +    QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject);
 +    QVERIFY(textPrivate != 0);
 +    QVERIFY(textPrivate->visibleImgTags.count() == 2);
 +
 +    delete textObject;
 +}
 +
 +void tst_qquicktext::imgTagsElide()
 +{
 +    QQuickView *canvas = createView(testFile("imgTagsElide.qml"));
 +    QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
 +    QVERIFY(myText != 0);
 +
 +    QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
 +    QVERIFY(textPrivate != 0);
 +    QVERIFY(textPrivate->visibleImgTags.count() == 0);
 +    myText->setMaximumLineCount(20);
 +    QTRY_VERIFY(textPrivate->visibleImgTags.count() == 1);
 +
 +    delete myText;
 +    delete canvas;
 +}
 +
 +void tst_qquicktext::imgTagsUpdates()
 +{
 +    QQuickView *canvas = createView(testFile("imgTagsUpdates.qml"));
 +    QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
 +    QVERIFY(myText != 0);
 +
 +    QSignalSpy spy(myText, SIGNAL(contentSizeChanged()));
 +
 +    QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
 +    QVERIFY(textPrivate != 0);
 +
 +    myText->setText("This is a heart<img src=\"images/heart200.png\">.");
 +    QVERIFY(textPrivate->visibleImgTags.count() == 1);
 +    QVERIFY(spy.count() == 1);
 +
 +    myText->setMaximumLineCount(2);
 +    myText->setText("This is another heart<img src=\"images/heart200.png\">.");
 +    QTRY_VERIFY(textPrivate->visibleImgTags.count() == 1);
 +
 +    // if maximumLineCount is set and the img tag doesn't have an explicit size
 +    // we relayout twice.
 +    QVERIFY(spy.count() == 3);
 +
 +    delete myText;
 +    delete canvas;
 +}
 +
 +void tst_qquicktext::imgTagsError()
 +{
 +    QString componentStr = "import QtQuick 2.0\nText { text: \"This is a starfish<img src=\\\"data/images/starfish_2.pn\\\" width=\\\"60\\\" height=\\\"60\\\">.\" }";
 +
 +    QQmlComponent textComponent(&engine);
 +    QTest::ignoreMessage(QtWarningMsg, "file::2:1: QML Text: Cannot open: file:data/images/starfish_2.pn");
 +    textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create());
 +
 +    QVERIFY(textObject != 0);
 +    delete textObject;
 +}
 +
 +void tst_qquicktext::fontSizeMode_data()
 +{
 +    QTest::addColumn<QString>("text");
-     QFETCH(bool, canElide);
++    QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog";
++    QTest::newRow("styled") << "<b>The quick red fox jumped over the lazy brown dog</b>";
 +}
 +
 +void tst_qquicktext::fontSizeMode()
 +{
 +    QFETCH(QString, text);
-     QQuickView *canvas = createView(testFile("fontSizeMode.qml"));
 +
-     if (canElide) {
-         // Elide won't affect the size with HorizontalFit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), horizontalFitWidth);
-         QCOMPARE(myText->contentHeight(), horizontalFitHeight);
-         myText->setElideMode(QQuickText::ElideLeft);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), horizontalFitWidth);
-         QCOMPARE(myText->contentHeight(), horizontalFitHeight);
-         myText->setElideMode(QQuickText::ElideMiddle);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), horizontalFitWidth);
-         QCOMPARE(myText->contentHeight(), horizontalFitHeight);
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    QScopedPointer<QQuickView> canvas(createView(testFile("fontSizeMode.qml")));
 +    canvas->show();
 +
 +    QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
 +    QVERIFY(myText != 0);
 +
 +    myText->setText(text);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    qreal originalWidth = myText->contentWidth();
 +    qreal originalHeight = myText->contentHeight();
 +
 +    // The original text unwrapped should exceed the width of the item.
 +    QVERIFY(originalWidth > myText->width());
 +    QVERIFY(originalHeight < myText->height());
 +
 +    QFont font = myText->font();
 +    font.setPixelSize(64);
 +
 +    myText->setFont(font);
 +    myText->setFontSizeMode(QQuickText::HorizontalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // Font size reduced to fit within the width of the item.
 +    qreal horizontalFitWidth = myText->contentWidth();
 +    qreal horizontalFitHeight = myText->contentHeight();
 +    QVERIFY(horizontalFitWidth <= myText->width() + 2); // rounding
 +    QVERIFY(horizontalFitHeight <= myText->height() + 2);
 +
-     if (canElide) {
-         // Elide won't affect the height of a single line with VerticalFit but will crop the width.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(myText->truncated());
-         QVERIFY(myText->contentWidth() <= myText->width() + 2);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
-         myText->setElideMode(QQuickText::ElideLeft);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(myText->truncated());
-         QVERIFY(myText->contentWidth() <= myText->width() + 2);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
-         myText->setElideMode(QQuickText::ElideMiddle);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(myText->truncated());
-         QVERIFY(myText->contentWidth() <= myText->width() + 2);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the size with HorizontalFit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
++    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideLeft);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
++    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideMiddle);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
++    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::VerticalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // Font size increased to fill the height of the item.
 +    qreal verticalFitHeight = myText->contentHeight();
 +    QVERIFY(myText->contentWidth() > myText->width());
 +    QVERIFY(verticalFitHeight <= myText->height() + 2);
 +    QVERIFY(verticalFitHeight > originalHeight);
 +
-     if (canElide) {
-         // Elide won't affect the size with Fit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), horizontalFitWidth);
-         QCOMPARE(myText->contentHeight(), horizontalFitHeight);
-         myText->setElideMode(QQuickText::ElideLeft);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), horizontalFitWidth);
-         QCOMPARE(myText->contentHeight(), horizontalFitHeight);
-         myText->setElideMode(QQuickText::ElideMiddle);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), horizontalFitWidth);
-         QCOMPARE(myText->contentHeight(), horizontalFitHeight);
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the height of a single line with VerticalFit but will crop the width.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(myText->truncated());
++    QVERIFY(myText->contentWidth() <= myText->width() + 2);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideLeft);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(myText->truncated());
++    QVERIFY(myText->contentWidth() <= myText->width() + 2);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideMiddle);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(myText->truncated());
++    QVERIFY(myText->contentWidth() <= myText->width() + 2);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::Fit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // Should be the same as HorizontalFit with no wrapping.
 +    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
 +    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
 +
-     if (canElide) {
-         // Elide won't affect the size with HorizontalFit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), horizontalFitWidth);
-         QCOMPARE(myText->contentHeight(), horizontalFitHeight);
++    // Elide won't affect the size with Fit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
++    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideLeft);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
++    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideMiddle);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
++    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::FixedSize);
 +    myText->setWrapMode(QQuickText::Wrap);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    originalWidth = myText->contentWidth();
 +    originalHeight = myText->contentHeight();
 +
 +    // The original text wrapped should exceed the height of the item.
 +    QVERIFY(originalWidth <= myText->width() + 2);
 +    QVERIFY(originalHeight > myText->height());
 +
 +    myText->setFontSizeMode(QQuickText::HorizontalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
 +    // same size as without text wrapping.
 +    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
 +    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the size with HorizontalFit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
++    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
 +
-     if (canElide) {
-         // Elide won't affect the height or width of a wrapped text with VerticalFit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::VerticalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // VerticalFit should reduce the size to the wrapped text within the vertical height.
 +    verticalFitHeight = myText->contentHeight();
 +    qreal verticalFitWidth = myText->contentWidth();
 +    QVERIFY(myText->contentWidth() <= myText->width() + 2);
 +    QVERIFY(verticalFitHeight <= myText->height() + 2);
 +    QVERIFY(verticalFitHeight < originalHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the height or width of a wrapped text with VerticalFit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-     if (canElide) {
-         // Elide won't affect the size with Fit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::Fit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // Should be the same as VerticalFit with wrapping.
 +    QCOMPARE(myText->contentWidth(), verticalFitWidth);
 +    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the size with Fit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-     if (canElide) {
-         // Elide won't affect the size with HorizontalFit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), horizontalFitWidth);
-         QCOMPARE(myText->contentHeight(), horizontalFitHeight);
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::FixedSize);
 +    myText->setMaximumLineCount(2);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    // The original text wrapped should exceed the height of the item.
 +    QVERIFY(originalWidth <= myText->width() + 2);
 +    QVERIFY(originalHeight > myText->height());
 +
 +    myText->setFontSizeMode(QQuickText::HorizontalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
 +    // same size as without text wrapping.
 +    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
 +    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the size with HorizontalFit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
++    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
 +
-     if (canElide) {
-         // Elide won't affect the height or width of a wrapped text with VerticalFit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::VerticalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // VerticalFit should reduce the size to the wrapped text within the vertical height.
 +    verticalFitHeight = myText->contentHeight();
 +    verticalFitWidth = myText->contentWidth();
 +    QVERIFY(myText->contentWidth() <= myText->width() + 2);
 +    QVERIFY(verticalFitHeight <= myText->height() + 2);
 +    QVERIFY(verticalFitHeight < originalHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the height or width of a wrapped text with VerticalFit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-     if (canElide) {
-         // Elide won't affect the size with Fit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::Fit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // Should be the same as VerticalFit with wrapping.
 +    QCOMPARE(myText->contentWidth(), verticalFitWidth);
 +    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the size with Fit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-     QTest::addColumn<bool>("canElide");
-     QTest::newRow("plain") << "The quick red fox jumped\n over the lazy brown dog" << true;
-     QTest::newRow("richtext") << "<b>The quick red fox jumped<br/> over the lazy brown dog</b>" << false;
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +}
 +
 +void tst_qquicktext::fontSizeModeMultiline_data()
 +{
 +    QTest::addColumn<QString>("text");
-     QFETCH(bool, canElide);
++    QTest::newRow("plain") << "The quick red fox jumped\n over the lazy brown dog";
++    QTest::newRow("styledtext") << "<b>The quick red fox jumped<br/> over the lazy brown dog</b>";
 +}
 +
 +void tst_qquicktext::fontSizeModeMultiline()
 +{
 +    QFETCH(QString, text);
-     QQuickView *canvas = createView(testFile("fontSizeMode.qml"));
 +
-     if (canElide) {
-         // Right eliding will remove the last line
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(myText->truncated());
-         QCOMPARE(myText->lineCount(), 1);
-         QVERIFY(myText->contentWidth() <= myText->width() + 2);
-         QVERIFY(myText->contentHeight() <= myText->height() + 2);
-         // Left or middle eliding wont have any effect.
-         myText->setElideMode(QQuickText::ElideLeft);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), horizontalFitWidth);
-         QCOMPARE(myText->contentHeight(), horizontalFitHeight);
-         myText->setElideMode(QQuickText::ElideMiddle);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), horizontalFitWidth);
-         QCOMPARE(myText->contentHeight(), horizontalFitHeight);
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    QScopedPointer<QQuickView> canvas(createView(testFile("fontSizeMode.qml")));
 +    canvas->show();
 +
 +    QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
 +    QVERIFY(myText != 0);
 +
 +    myText->setText(text);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    qreal originalWidth = myText->contentWidth();
 +    qreal originalHeight = myText->contentHeight();
 +    QCOMPARE(myText->lineCount(), 2);
 +
 +    // The original text unwrapped should exceed the width and height of the item.
 +    QVERIFY(originalWidth > myText->width());
 +    QVERIFY(originalHeight > myText->height());
 +
 +    QFont font = myText->font();
 +    font.setPixelSize(64);
 +
 +    myText->setFont(font);
 +    myText->setFontSizeMode(QQuickText::HorizontalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // Font size reduced to fit within the width of the item.
 +    QCOMPARE(myText->lineCount(), 2);
 +    qreal horizontalFitWidth = myText->contentWidth();
 +    qreal horizontalFitHeight = myText->contentHeight();
 +    QVERIFY(horizontalFitWidth <= myText->width() + 2); // rounding
 +    QVERIFY(horizontalFitHeight > myText->height());
 +
-     if (canElide) {
-         // Elide will have no effect.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QVERIFY(myText->contentWidth() <= myText->width() + 2);
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
-         myText->setElideMode(QQuickText::ElideLeft);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
-         myText->setElideMode(QQuickText::ElideMiddle);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Right eliding will remove the last line
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(myText->truncated());
++    QCOMPARE(myText->lineCount(), 1);
++    QVERIFY(myText->contentWidth() <= myText->width() + 2);
++    QVERIFY(myText->contentHeight() <= myText->height() + 2);
++
++    // Left or middle eliding wont have any effect.
++    myText->setElideMode(QQuickText::ElideLeft);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
++    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideMiddle);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
++    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::VerticalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // Font size reduced to fit within the height of the item.
 +    qreal verticalFitWidth = myText->contentWidth();
 +    qreal verticalFitHeight = myText->contentHeight();
 +    QVERIFY(verticalFitWidth <= myText->width() + 2);
 +    QVERIFY(verticalFitHeight <= myText->height() + 2);
 +
-     if (canElide) {
-         // Elide won't affect the size with Fit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
-         myText->setElideMode(QQuickText::ElideLeft);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
-         myText->setElideMode(QQuickText::ElideMiddle);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide will have no effect.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QVERIFY(myText->contentWidth() <= myText->width() + 2);
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideLeft);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideMiddle);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::Fit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // Should be the same as VerticalFit with no wrapping.
 +    QCOMPARE(myText->contentWidth(), verticalFitWidth);
 +    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-     if (canElide) {
-         // Text will be elided vertically with HorizontalFit
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(myText->truncated());
-         QVERIFY(myText->contentWidth() <= myText->width() + 2);
-         QVERIFY(myText->contentHeight() <= myText->height() + 2);
++    // Elide won't affect the size with Fit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideLeft);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideMiddle);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
++
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::FixedSize);
 +    myText->setWrapMode(QQuickText::Wrap);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    originalWidth = myText->contentWidth();
 +    originalHeight = myText->contentHeight();
 +
 +    // The original text wrapped should exceed the height of the item.
 +    QVERIFY(originalWidth <= myText->width() + 2);
 +    QVERIFY(originalHeight > myText->height());
 +
 +    myText->setFontSizeMode(QQuickText::HorizontalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
 +    // same size as without text wrapping.
 +    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
 +    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Text will be elided vertically with HorizontalFit
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(myText->truncated());
++    QVERIFY(myText->contentWidth() <= myText->width() + 2);
++    QVERIFY(myText->contentHeight() <= myText->height() + 2);
 +
-     if (canElide) {
-         // Elide won't affect the height or width of a wrapped text with VerticalFit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::VerticalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // VerticalFit should reduce the size to the wrapped text within the vertical height.
 +    verticalFitHeight = myText->contentHeight();
 +    verticalFitWidth = myText->contentWidth();
 +    QVERIFY(myText->contentWidth() <= myText->width() + 2);
 +    QVERIFY(verticalFitHeight <= myText->height() + 2);
 +    QVERIFY(verticalFitHeight < originalHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the height or width of a wrapped text with VerticalFit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-     if (canElide) {
-         // Elide won't affect the size with Fit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::Fit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // Should be the same as VerticalFit with wrapping.
 +    QCOMPARE(myText->contentWidth(), verticalFitWidth);
 +    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the size with Fit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-     if (canElide) {
-         // Elide won't affect the size with HorizontalFit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(myText->truncated());
-         QVERIFY(myText->contentWidth() <= myText->width() + 2);
-         QVERIFY(myText->contentHeight() <= myText->height() + 2);
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::FixedSize);
 +    myText->setMaximumLineCount(2);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    // The original text wrapped should exceed the height of the item.
 +    QVERIFY(originalWidth <= myText->width() + 2);
 +    QVERIFY(originalHeight > myText->height());
 +
 +    myText->setFontSizeMode(QQuickText::HorizontalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // HorizontalFit should reduce the font size to minimize wrapping, which brings it back to the
 +    // same size as without text wrapping.
 +    QCOMPARE(myText->contentWidth(), horizontalFitWidth);
 +    QCOMPARE(myText->contentHeight(), horizontalFitHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the size with HorizontalFit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(myText->truncated());
++    QVERIFY(myText->contentWidth() <= myText->width() + 2);
++    QVERIFY(myText->contentHeight() <= myText->height() + 2);
 +
-     if (canElide) {
-         // Elide won't affect the height or width of a wrapped text with VerticalFit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::VerticalFit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // VerticalFit should reduce the size to the wrapped text within the vertical height.
 +    verticalFitHeight = myText->contentHeight();
 +    verticalFitWidth = myText->contentWidth();
 +    QVERIFY(myText->contentWidth() <= myText->width() + 2);
 +    QVERIFY(verticalFitHeight <= myText->height() + 2);
 +    QVERIFY(verticalFitHeight < originalHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the height or width of a wrapped text with VerticalFit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-     if (canElide) {
-         // Elide won't affect the size with Fit.
-         myText->setElideMode(QQuickText::ElideRight);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-         QVERIFY(!myText->truncated());
-         QCOMPARE(myText->contentWidth(), verticalFitWidth);
-         QCOMPARE(myText->contentHeight(), verticalFitHeight);
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    myText->setFontSizeMode(QQuickText::Fit);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    // Should be the same as VerticalFit with wrapping.
 +    QCOMPARE(myText->contentWidth(), verticalFitWidth);
 +    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
-         myText->setElideMode(QQuickText::ElideNone);
-         QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
-     }
++    // Elide won't affect the size with Fit.
++    myText->setElideMode(QQuickText::ElideRight);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
++    QVERIFY(!myText->truncated());
++    QCOMPARE(myText->contentWidth(), verticalFitWidth);
++    QCOMPARE(myText->contentHeight(), verticalFitHeight);
 +
- #ifdef Q_OS_MAC
-     QEXPECT_FAIL("Wrap", "QTBUG-24310", Continue);
- #endif
++    myText->setElideMode(QQuickText::ElideNone);
++    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +}
 +
 +void tst_qquicktext::multilengthStrings_data()
 +{
 +    QTest::addColumn<QString>("source");
 +    QTest::newRow("No Wrap") << testFile("multilengthStrings.qml");
 +    QTest::newRow("Wrap") << testFile("multilengthStringsWrapped.qml");
 +}
 +
 +void tst_qquicktext::multilengthStrings()
 +{
 +    QFETCH(QString, source);
 +
 +    QScopedPointer<QQuickView> canvas(createView(source));
 +    canvas->show();
 +
 +    QQuickText *myText = canvas->rootObject()->findChild<QQuickText*>("myText");
 +    QVERIFY(myText != 0);
 +
 +    const QString longText = "the quick brown fox jumped over the lazy dog";
 +    const QString mediumText = "the brown fox jumped over the dog";
 +    const QString shortText = "fox jumped dog";
 +
 +    myText->setText(longText);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    const qreal longWidth = myText->contentWidth();
 +    const qreal longHeight = myText->contentHeight();
 +
 +    myText->setText(mediumText);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    const qreal mediumWidth = myText->contentWidth();
 +    const qreal mediumHeight = myText->contentHeight();
 +
 +    myText->setText(shortText);
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +    const qreal shortWidth = myText->contentWidth();
 +    const qreal shortHeight = myText->contentHeight();
 +
 +    myText->setElideMode(QQuickText::ElideRight);
 +    myText->setText(longText + QLatin1Char('\x9c') + mediumText + QLatin1Char('\x9c') + shortText);
 +
 +    myText->setSize(QSizeF(longWidth, longHeight));
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    QCOMPARE(myText->contentWidth(), longWidth);
 +    QCOMPARE(myText->contentHeight(), longHeight);
 +    QCOMPARE(myText->truncated(), false);
 +
 +    myText->setSize(QSizeF(mediumWidth, mediumHeight));
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    QCOMPARE(myText->contentWidth(), mediumWidth);
 +    QCOMPARE(myText->contentHeight(), mediumHeight);
 +    QCOMPARE(myText->truncated(), true);
 +
 +    myText->setSize(QSizeF(shortWidth, shortHeight));
 +    QTRY_COMPARE(QQuickItemPrivate::get(myText)->polishScheduled, false);
 +
 +    QCOMPARE(myText->contentWidth(), shortWidth);
 +    QCOMPARE(myText->contentHeight(), shortHeight);
 +    QCOMPARE(myText->truncated(), true);
 +}
 +
++void tst_qquicktext::fontFormatSizes_data()
++{
++    QTest::addColumn<QString>("text");
++    QTest::addColumn<QString>("textWithTag");
++    QTest::addColumn<bool>("fontIsBigger");
++
++    QTest::newRow("fs1") << "Hello world!" << "Hello <font size=\"1\">world</font>!" << false;
++    QTest::newRow("fs2") << "Hello world!" << "Hello <font size=\"2\">world</font>!" << false;
++    QTest::newRow("fs3") << "Hello world!" << "Hello <font size=\"3\">world</font>!" << false;
++    QTest::newRow("fs4") << "Hello world!" << "Hello <font size=\"4\">world</font>!" << true;
++    QTest::newRow("fs5") << "Hello world!" << "Hello <font size=\"5\">world</font>!" << true;
++    QTest::newRow("fs6") << "Hello world!" << "Hello <font size=\"6\">world</font>!" << true;
++    QTest::newRow("fs7") << "Hello world!" << "Hello <font size=\"7\">world</font>!" << true;
++    QTest::newRow("h1") << "This is<br/>a font<br/> size test." << "This is <h1>a font</h1> size test." << true;
++    QTest::newRow("h2") << "This is<br/>a font<br/> size test." << "This is <h2>a font</h2> size test." << true;
++    QTest::newRow("h3") << "This is<br/>a font<br/> size test." << "This is <h3>a font</h3> size test." << true;
++    QTest::newRow("h4") << "This is<br/>a font<br/> size test." << "This is <h4>a font</h4> size test." << true;
++    QTest::newRow("h5") << "This is<br/>a font<br/> size test." << "This is <h5>a font</h5> size test." << false;
++    QTest::newRow("h6") << "This is<br/>a font<br/> size test." << "This is <h6>a font</h6> size test." << false;
++}
++
++void tst_qquicktext::fontFormatSizes()
++{
++    QFETCH(QString, text);
++    QFETCH(QString, textWithTag);
++    QFETCH(bool, fontIsBigger);
++
++    QQuickView *view = new QQuickView;
++    {
++        view->setSource(testFileUrl("pointFontSizes.qml"));
++        view->show();
++
++        QQuickText *qtext = view->rootObject()->findChild<QQuickText*>("text");
++        QQuickText *qtextWithTag = view->rootObject()->findChild<QQuickText*>("textWithTag");
++        QVERIFY(qtext != 0);
++        QVERIFY(qtextWithTag != 0);
++
++        qtext->setText(text);
++        qtextWithTag->setText(textWithTag);
++
++        for (int size = 6; size < 100; size += 4) {
++            view->rootObject()->setProperty("pointSize", size);
++            if (fontIsBigger)
++                QVERIFY(qtext->height() <= qtextWithTag->height());
++            else
++                QVERIFY(qtext->height() >= qtextWithTag->height());
++        }
++    }
++
++    {
++        view->setSource(testFileUrl("pixelFontSizes.qml"));
++        QQuickText *qtext = view->rootObject()->findChild<QQuickText*>("text");
++        QQuickText *qtextWithTag = view->rootObject()->findChild<QQuickText*>("textWithTag");
++        QVERIFY(qtext != 0);
++        QVERIFY(qtextWithTag != 0);
++
++        qtext->setText(text);
++        qtextWithTag->setText(textWithTag);
++
++        for (int size = 6; size < 100; size += 4) {
++            view->rootObject()->setProperty("pixelSize", size);
++            if (fontIsBigger)
++                QVERIFY(qtext->height() <= qtextWithTag->height());
++            else
++                QVERIFY(qtext->height() >= qtextWithTag->height());
++        }
++    }
++    delete view;
++}
++
 +QTEST_MAIN(tst_qquicktext)
 +
 +#include "tst_qquicktext.moc"
index 314a523,0000000..85a9033
mode 100644,000000..100644
--- /dev/null
@@@ -1,3884 -1,0 +1,3881 @@@
-         qreal metricWidth = ceil(layout.boundingRect().width());
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <qtest.h>
 +#include <QtTest/QSignalSpy>
 +#include "../../shared/testhttpserver.h"
 +#include <math.h>
 +#include <QFile>
 +#include <QTextDocument>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlcontext.h>
 +#include <QtQml/qqmlexpression.h>
 +#include <QtQml/qqmlcomponent.h>
 +#include <QtGui/qguiapplication.h>
 +#include <private/qquicktextedit_p.h>
 +#include <private/qquicktextedit_p_p.h>
 +#include <private/qquicktext_p_p.h>
 +#include <QFontMetrics>
 +#include <QtQuick/QQuickView>
 +#include <QDir>
 +#include <QStyle>
 +#include <QInputMethod>
 +#include <QClipboard>
 +#include <QMimeData>
 +#include <private/qquicktextcontrol_p.h>
 +#include "../../shared/util.h"
 +#include "../../shared/platforminputcontext.h"
 +#include <private/qinputmethod_p.h>
 +
 +#ifdef Q_OS_MAC
 +#include <Carbon/Carbon.h>
 +#endif
 +
 +
 +Q_DECLARE_METATYPE(QQuickTextEdit::SelectionMode)
 +DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
 +
 +QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
 +{
 +    // XXX This will be replaced by some clever persistent platform image store.
 +    QString persistent_dir = QQmlDataTest::instance()->dataDirectory();
 +    QString arch = "unknown-architecture"; // QTest needs to help with this.
 +
 +    QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
 +
 +    if (!QFile::exists(expectfile)) {
 +        actual.save(expectfile);
 +        qWarning() << "created" << expectfile;
 +    }
 +
 +    return expectfile;
 +}
 +
 +typedef QPair<int, QChar> Key;
 +
 +class tst_qquicktextedit : public QQmlDataTest
 +
 +{
 +    Q_OBJECT
 +public:
 +    tst_qquicktextedit();
 +
 +private slots:
 +    void cleanup();
 +    void text();
 +    void width();
 +    void wrap();
 +    void textFormat();
 +    void alignments();
 +    void alignments_data();
 +
 +    // ### these tests may be trivial
 +    void hAlign();
 +    void hAlign_RightToLeft();
 +    void vAlign();
 +    void font();
 +    void color();
 +    void textMargin();
 +    void persistentSelection();
 +    void focusOnPress();
 +    void selection();
 +    void isRightToLeft_data();
 +    void isRightToLeft();
 +    void keySelection();
 +    void moveCursorSelection_data();
 +    void moveCursorSelection();
 +    void moveCursorSelectionSequence_data();
 +    void moveCursorSelectionSequence();
 +    void mouseSelection_data();
 +    void mouseSelection();
 +    void mouseSelectionMode_data();
 +    void mouseSelectionMode();
 +    void dragMouseSelection();
 +    void inputMethodHints();
 +
 +    void positionAt();
 +
 +    void linkActivated();
 +
 +    void cursorDelegate_data();
 +    void cursorDelegate();
 +    void cursorVisible();
 +    void delegateLoading_data();
 +    void delegateLoading();
 +    void navigation();
 +    void readOnly();
 +    void copyAndPaste();
 +    void canPaste();
 +    void canPasteEmpty();
 +    void textInput();
 +    void inputMethodUpdate();
 +    void openInputPanel();
 +    void geometrySignals();
 +    void pastingRichText_QTBUG_14003();
 +    void implicitSize_data();
 +    void implicitSize();
 +    void contentSize();
 +
 +    void preeditCursorRectangle();
 +    void inputMethodComposing();
 +    void cursorRectangleSize();
 +
 +    void getText_data();
 +    void getText();
 +    void getFormattedText_data();
 +    void getFormattedText();
 +    void insert_data();
 +    void insert();
 +    void remove_data();
 +    void remove();
 +
 +    void keySequence_data();
 +    void keySequence();
 +
 +    void undo_data();
 +    void undo();
 +    void redo_data();
 +    void redo();
 +    void undo_keypressevents_data();
 +    void undo_keypressevents();
 +
 +    void baseUrl();
 +    void embeddedImages();
 +    void embeddedImages_data();
 +
 +    void emptytags_QTBUG_22058();
 +
 +private:
 +    void simulateKeys(QWindow *window, const QList<Key> &keys);
 +    void simulateKeys(QWindow *window, const QKeySequence &sequence);
 +
 +    void simulateKey(QQuickView *, int key, Qt::KeyboardModifiers modifiers = 0);
 +
 +    QStringList standard;
 +    QStringList richText;
 +
 +    QStringList hAlignmentStrings;
 +    QStringList vAlignmentStrings;
 +
 +    QList<Qt::Alignment> vAlignments;
 +    QList<Qt::Alignment> hAlignments;
 +
 +    QStringList colorStrings;
 +
 +    QQmlEngine engine;
 +};
 +
 +typedef QList<int> IntList;
 +Q_DECLARE_METATYPE(IntList)
 +
 +typedef QList<Key> KeyList;
 +Q_DECLARE_METATYPE(KeyList)
 +
 +Q_DECLARE_METATYPE(QQuickTextEdit::TextFormat)
 +
 +void tst_qquicktextedit::simulateKeys(QWindow *window, const QList<Key> &keys)
 +{
 +    for (int i = 0; i < keys.count(); ++i) {
 +        const int key = keys.at(i).first;
 +        const int modifiers = key & Qt::KeyboardModifierMask;
 +        const QString text = !keys.at(i).second.isNull() ? QString(keys.at(i).second) : QString();
 +
 +        QKeyEvent press(QEvent::KeyPress, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
 +        QKeyEvent release(QEvent::KeyRelease, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
 +
 +        QGuiApplication::sendEvent(window, &press);
 +        QGuiApplication::sendEvent(window, &release);
 +    }
 +}
 +
 +void tst_qquicktextedit::simulateKeys(QWindow *window, const QKeySequence &sequence)
 +{
 +    for (int i = 0; i < sequence.count(); ++i) {
 +        const int key = sequence[i];
 +        const int modifiers = key & Qt::KeyboardModifierMask;
 +
 +        QTest::keyClick(window, Qt::Key(key & ~modifiers), Qt::KeyboardModifiers(modifiers));
 +    }
 +}
 +
 +QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
 +{
 +    for (int i = 0; i < sequence.count(); ++i)
 +        keys << Key(sequence[i], QChar());
 +    return keys;
 +}
 +
 +template <int N> QList<Key> &operator <<(QList<Key> &keys, const char (&characters)[N])
 +{
 +    for (int i = 0; i < N - 1; ++i) {
 +        int key = QTest::asciiToKey(characters[i]);
 +        QChar character = QLatin1Char(characters[i]);
 +        keys << Key(key, character);
 +    }
 +    return keys;
 +}
 +
 +QList<Key> &operator <<(QList<Key> &keys, Qt::Key key)
 +{
 +    keys << Key(key, QChar());
 +    return keys;
 +}
 +
 +tst_qquicktextedit::tst_qquicktextedit()
 +{
 +    standard << "the quick brown fox jumped over the lazy dog"
 +             << "the quick brown fox\n jumped over the lazy dog"
 +             << "Hello, world!"
 +             << "!dlrow ,olleH";
 +
 +    richText << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a> jumped over the <b>lazy</b> dog</i>"
 +             << "<i>the <b>quick</b> brown <a href=\\\"http://www.google.com\\\">fox</a><br>jumped over the <b>lazy</b> dog</i>";
 +
 +    hAlignmentStrings << "AlignLeft"
 +                      << "AlignRight"
 +                      << "AlignHCenter";
 +
 +    vAlignmentStrings << "AlignTop"
 +                      << "AlignBottom"
 +                      << "AlignVCenter";
 +
 +    hAlignments << Qt::AlignLeft
 +                << Qt::AlignRight
 +                << Qt::AlignHCenter;
 +
 +    vAlignments << Qt::AlignTop
 +                << Qt::AlignBottom
 +                << Qt::AlignVCenter;
 +
 +    colorStrings << "aliceblue"
 +                 << "antiquewhite"
 +                 << "aqua"
 +                 << "darkkhaki"
 +                 << "darkolivegreen"
 +                 << "dimgray"
 +                 << "palevioletred"
 +                 << "lightsteelblue"
 +                 << "#000000"
 +                 << "#AAAAAA"
 +                 << "#FFFFFF"
 +                 << "#2AC05F";
 +                 //
 +                 // need a different test to do alpha channel test
 +                 // << "#AA0011DD"
 +                 // << "#00F16B11";
 +                 //
 +}
 +
 +void tst_qquicktextedit::cleanup()
 +{
 +    // ensure not even skipped tests with custom input context leave it dangling
 +    QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
 +    inputMethodPrivate->testContext = 0;
 +}
 +
 +void tst_qquicktextedit::text()
 +{
 +    {
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData("import QtQuick 2.0\nTextEdit {  text: \"\"  }", QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->text(), QString(""));
 +        QCOMPARE(textEditObject->length(), 0);
 +    }
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->text(), standard.at(i));
 +        QCOMPARE(textEditObject->length(), standard.at(i).length());
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + richText.at(i) + "\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +
 +        QString expected = richText.at(i);
 +        expected.replace(QRegExp("\\\\(.)"),"\\1");
 +        QCOMPARE(textEditObject->text(), expected);
 +        QCOMPARE(textEditObject->length(), expected.length());
 +    }
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.RichText; text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +
 +        QString actual = textEditObject->text();
 +        QString expected = standard.at(i);
 +        actual.remove(QRegExp(".*<body[^>]*>"));
 +        actual.remove(QRegExp("(<[^>]*>)+"));
 +        expected.remove("\n");
 +        QCOMPARE(actual.simplified(), expected);
 +        QCOMPARE(textEditObject->length(), expected.length());
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.RichText; text: \"" + richText.at(i) + "\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QString actual = textEditObject->text();
 +        QString expected = richText.at(i);
 +        actual.replace(QRegExp(".*<body[^>]*>"),"");
 +        actual.replace(QRegExp("(<[^>]*>)+"),"<>");
 +        expected.replace(QRegExp("(<[^>]*>)+"),"<>");
 +        QCOMPARE(actual.simplified(),expected.simplified());
 +
 +        expected.replace("<>", " ");
 +        QCOMPARE(textEditObject->length(), expected.simplified().length());
 +    }
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.AutoText; text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->text(), standard.at(i));
 +        QCOMPARE(textEditObject->length(), standard.at(i).length());
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.AutoText; text: \"" + richText.at(i) + "\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QString actual = textEditObject->text();
 +        QString expected = richText.at(i);
 +        actual.replace(QRegExp(".*<body[^>]*>"),"");
 +        actual.replace(QRegExp("(<[^>]*>)+"),"<>");
 +        expected.replace(QRegExp("(<[^>]*>)+"),"<>");
 +        QCOMPARE(actual.simplified(),expected.simplified());
 +
 +        expected.replace("<>", " ");
 +        QCOMPARE(textEditObject->length(), expected.simplified().length());
 +    }
 +}
 +
 +void tst_qquicktextedit::width()
 +{
 +    // uses Font metrics to find the width for standard and document to find the width for rich
 +    {
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData("import QtQuick 2.0\nTextEdit {  text: \"\" }", QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->width(), 0.0);
 +    }
 +
 +    bool requiresUnhintedMetrics = !qmlDisableDistanceField();
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QString s = standard.at(i);
 +        s.replace(QLatin1Char('\n'), QChar::LineSeparator);
 +
 +        QTextLayout layout(s);
 +        layout.setFont(textEditObject->font());
 +        layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
 +        if (requiresUnhintedMetrics) {
 +            QTextOption option;
 +            option.setUseDesignMetrics(true);
 +            layout.setTextOption(option);
 +        }
 +
 +        layout.beginLayout();
 +        forever {
 +            QTextLine line = layout.createLine();
 +            if (!line.isValid())
 +                break;
 +        }
 +
 +        layout.endLayout();
 +
-         QCOMPARE(textEditObject->width(), qreal(metricWidth));
++        qreal metricWidth = layout.boundingRect().width();
 +
 +        QVERIFY(textEditObject != 0);
-         int documentWidth = ceil(document.idealWidth());
++        QCOMPARE(textEditObject->width(), metricWidth);
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        QTextDocument document;
 +        document.setHtml(richText.at(i));
 +        document.setDocumentMargin(0);
 +        if (requiresUnhintedMetrics)
 +            document.setUseDesignMetrics(true);
 +
-         QCOMPARE(textEditObject->width(), qreal(documentWidth));
++        qreal documentWidth = document.idealWidth();
 +
 +        QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.RichText; text: \"" + richText.at(i) + "\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
-         QPalette pal = textEditPrivate->control->palette();
++        QCOMPARE(textEditObject->width(), documentWidth);
 +    }
 +}
 +
 +void tst_qquicktextedit::wrap()
 +{
 +    // for specified width and wrap set true
 +    {
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData("import QtQuick 2.0\nTextEdit {  text: \"\"; wrapMode: TextEdit.WordWrap; width: 300 }", QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->width(), 300.);
 +    }
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  wrapMode: TextEdit.WordWrap; width: 300; text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->width(), 300.);
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  wrapMode: TextEdit.WordWrap; width: 300; text: \"" + richText.at(i) + "\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->width(), 300.);
 +    }
 +
 +}
 +
 +void tst_qquicktextedit::textFormat()
 +{
 +    {
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData("import QtQuick 2.0\nTextEdit { text: \"Hello\"; textFormat: Text.RichText }", QUrl::fromLocalFile(""));
 +        QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QVERIFY(textObject->textFormat() == QQuickTextEdit::RichText);
 +    }
 +    {
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData("import QtQuick 2.0\nTextEdit { text: \"<b>Hello</b>\"; textFormat: Text.PlainText }", QUrl::fromLocalFile(""));
 +        QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QVERIFY(textObject->textFormat() == QQuickTextEdit::PlainText);
 +    }
 +}
 +
 +void tst_qquicktextedit::alignments_data()
 +{
 +    QTest::addColumn<int>("hAlign");
 +    QTest::addColumn<int>("vAlign");
 +    QTest::addColumn<QString>("expectfile");
 +
 +    QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << "alignments_lt";
 +    QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << "alignments_rt";
 +    QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << "alignments_ct";
 +
 +    QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << "alignments_lb";
 +    QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << "alignments_rb";
 +    QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << "alignments_cb";
 +
 +    QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << "alignments_lc";
 +    QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << "alignments_rc";
 +    QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << "alignments_cc";
 +}
 +
 +
 +void tst_qquicktextedit::alignments()
 +{
 +    QSKIP("Image comparison of text is almost guaranteed to fail during development");
 +
 +    QFETCH(int, hAlign);
 +    QFETCH(int, vAlign);
 +    QFETCH(QString, expectfile);
 +
 +    QQuickView canvas(testFileUrl("alignments.qml"));
 +
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +
 +    QObject *ob = canvas.rootObject();
 +    QVERIFY(ob != 0);
 +    ob->setProperty("horizontalAlignment",hAlign);
 +    ob->setProperty("verticalAlignment",vAlign);
 +    QTRY_COMPARE(ob->property("running").toBool(),false);
 +    QImage actual = canvas.grabFrameBuffer();
 +
 +    expectfile = createExpectedFileIfNotFound(expectfile, actual);
 +
 +    QImage expect(expectfile);
 +
 +    QCOMPARE(actual,expect);
 +}
 +
 +
 +//the alignment tests may be trivial o.oa
 +void tst_qquicktextedit::hAlign()
 +{
 +    //test one align each, and then test if two align fails.
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        for (int j=0; j < hAlignmentStrings.size(); j++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nTextEdit {  horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
 +            QQmlComponent texteditComponent(&engine);
 +            texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +            QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +            QVERIFY(textEditObject != 0);
 +            QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
 +        }
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        for (int j=0; j < hAlignmentStrings.size(); j++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nTextEdit {  horizontalAlignment: \"" + hAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
 +            QQmlComponent texteditComponent(&engine);
 +            texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +            QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +            QVERIFY(textEditObject != 0);
 +            QCOMPARE((int)textEditObject->hAlign(), (int)hAlignments.at(j));
 +        }
 +    }
 +
 +}
 +
 +void tst_qquicktextedit::hAlign_RightToLeft()
 +{
 +    PlatformInputContext platformInputContext;
 +    QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
 +    inputMethodPrivate->testContext = &platformInputContext;
 +
 +    QQuickView canvas(testFileUrl("horizontalAlignment_RightToLeft.qml"));
 +    QQuickTextEdit *textEdit = canvas.rootObject()->findChild<QQuickTextEdit*>("text");
 +    QVERIFY(textEdit != 0);
 +    canvas.show();
 +
 +    const QString rtlText = textEdit->text();
 +
 +    // implicit alignment should follow the reading direction of text
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
 +
 +    // explicitly left aligned
 +    textEdit->setHAlign(QQuickTextEdit::AlignLeft);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
 +    QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
 +
 +    // explicitly right aligned
 +    textEdit->setHAlign(QQuickTextEdit::AlignRight);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
 +
 +    QString textString = textEdit->text();
 +    textEdit->setText(QString("<i>") + textString + QString("</i>"));
 +    textEdit->resetHAlign();
 +
 +    // implicitly aligned rich text should follow the reading direction of RTL text
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
 +    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
 +
 +    // explicitly left aligned rich text
 +    textEdit->setHAlign(QQuickTextEdit::AlignLeft);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
 +    QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
 +    QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
 +
 +    // explicitly right aligned rich text
 +    textEdit->setHAlign(QQuickTextEdit::AlignRight);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
 +    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
 +
 +    textEdit->setText(textString);
 +
 +    // explicitly center aligned
 +    textEdit->setHAlign(QQuickTextEdit::AlignHCenter);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignHCenter);
 +    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
 +
 +    // reseted alignment should go back to following the text reading direction
 +    textEdit->resetHAlign();
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
 +
 +    // mirror the text item
 +    QQuickItemPrivate::get(textEdit)->setLayoutMirror(true);
 +
 +    // mirrored implicit alignment should continue to follow the reading direction of the text
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
 +    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
 +
 +    // mirrored explicitly right aligned behaves as left aligned
 +    textEdit->setHAlign(QQuickTextEdit::AlignRight);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignLeft);
 +    QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
 +
 +    // mirrored explicitly left aligned behaves as right aligned
 +    textEdit->setHAlign(QQuickTextEdit::AlignLeft);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
 +    QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
 +    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
 +
 +    // disable mirroring
 +    QQuickItemPrivate::get(textEdit)->setLayoutMirror(false);
 +    textEdit->resetHAlign();
 +
 +    // English text should be implicitly left aligned
 +    textEdit->setText("Hello world!");
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
 +    QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
 +
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +
 +    textEdit->setText(QString());
 +    { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
 +
 +    // Clear pre-edit text.  TextEdit should maybe do this itself on setText, but that may be
 +    // redundant as an actual input method may take care of it.
 +    { QInputMethodEvent ev; QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
 +
 +    // empty text with implicit alignment follows the system locale-based
 +    // keyboard input direction from qApp->inputMethod()->inputDirection
 +    textEdit->setText("");
 +    platformInputContext.setInputDirection(Qt::LeftToRight);
 +    QVERIFY(qApp->inputMethod()->inputDirection() == Qt::LeftToRight);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
 +    QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
 +
 +    QSignalSpy cursorRectangleSpy(textEdit, SIGNAL(cursorRectangleChanged()));
 +
 +    platformInputContext.setInputDirection(Qt::RightToLeft);
 +    QCOMPARE(cursorRectangleSpy.count(), 1);
 +    QVERIFY(qApp->inputMethod()->inputDirection() == Qt::RightToLeft);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
 +
 +    // set input direction while having content
 +    platformInputContext.setInputDirection(Qt::LeftToRight);
 +    textEdit->setText("a");
 +    textEdit->setCursorPosition(1);
 +    platformInputContext.setInputDirection(Qt::RightToLeft);
 +    QTest::keyClick(&canvas, Qt::Key_Backspace);
 +    QVERIFY(textEdit->text().isEmpty());
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QVERIFY(textEdit->cursorRectangle().left() > canvas.width()/2);
 +
 +    // input direction changed while not having focus
 +    platformInputContext.setInputDirection(Qt::LeftToRight);
 +    textEdit->setFocus(false);
 +    platformInputContext.setInputDirection(Qt::RightToLeft);
 +    textEdit->setFocus(true);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QVERIFY(textEdit->cursorRectangle().left() > canvas.width()/2);
 +
 +    textEdit->setHAlign(QQuickTextEdit::AlignRight);
 +    QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
 +    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
 +}
 +
 +void tst_qquicktextedit::vAlign()
 +{
 +    //test one align each, and then test if two align fails.
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        for (int j=0; j < vAlignmentStrings.size(); j++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nTextEdit {  verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + standard.at(i) + "\" }";
 +            QQmlComponent texteditComponent(&engine);
 +            texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +            QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +            QVERIFY(textEditObject != 0);
 +            QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
 +        }
 +    }
 +
 +    for (int i = 0; i < richText.size(); i++)
 +    {
 +        for (int j=0; j < vAlignmentStrings.size(); j++)
 +        {
 +            QString componentStr = "import QtQuick 2.0\nTextEdit {  verticalAlignment: \"" + vAlignmentStrings.at(j) + "\"; text: \"" + richText.at(i) + "\" }";
 +            QQmlComponent texteditComponent(&engine);
 +            texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +            QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +            QVERIFY(textEditObject != 0);
 +            QCOMPARE((int)textEditObject->vAlign(), (int)vAlignments.at(j));
 +        }
 +    }
 +
 +    QQmlComponent texteditComponent(&engine);
 +    texteditComponent.setData(
 +                "import QtQuick 2.0\n"
 +                "TextEdit { width: 100; height: 100; text: \"Hello World\" }", QUrl());
 +    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +    QVERIFY(textEditObject != 0);
 +
 +    QCOMPARE(textEditObject->vAlign(), QQuickTextEdit::AlignTop);
 +    QVERIFY(textEditObject->cursorRectangle().bottom() < 50);
 +    QVERIFY(textEditObject->positionToRectangle(0).bottom() < 50);
 +
 +    // bottom aligned
 +    textEditObject->setVAlign(QQuickTextEdit::AlignBottom);
 +    QCOMPARE(textEditObject->vAlign(), QQuickTextEdit::AlignBottom);
 +    QVERIFY(textEditObject->cursorRectangle().top() > 50);
 +    QVERIFY(textEditObject->positionToRectangle(0).top() > 50);
 +
 +    // explicitly center aligned
 +    textEditObject->setVAlign(QQuickTextEdit::AlignVCenter);
 +    QCOMPARE(textEditObject->vAlign(), QQuickTextEdit::AlignVCenter);
 +    QVERIFY(textEditObject->cursorRectangle().top() < 50);
 +    QVERIFY(textEditObject->cursorRectangle().bottom() > 50);
 +    QVERIFY(textEditObject->positionToRectangle(0).top() < 50);
 +    QVERIFY(textEditObject->positionToRectangle(0).bottom() > 50);
 +}
 +
 +void tst_qquicktextedit::font()
 +{
 +    //test size, then bold, then italic, then family
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  font.pointSize: 40; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->font().pointSize(), 40);
 +        QCOMPARE(textEditObject->font().bold(), false);
 +        QCOMPARE(textEditObject->font().italic(), false);
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  font.bold: true; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->font().bold(), true);
 +        QCOMPARE(textEditObject->font().italic(), false);
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  font.italic: true; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->font().italic(), true);
 +        QCOMPARE(textEditObject->font().bold(), false);
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  font.family: \"Helvetica\"; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->font().family(), QString("Helvetica"));
 +        QCOMPARE(textEditObject->font().bold(), false);
 +        QCOMPARE(textEditObject->font().italic(), false);
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  font.family: \"\"; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->font().family(), QString(""));
 +    }
 +}
 +
 +void tst_qquicktextedit::color()
 +{
 +    //test initial color
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QQuickTextEditPrivate *textEditPrivate = static_cast<QQuickTextEditPrivate*>(QQuickItemPrivate::get(textEditObject));
 +
 +        QVERIFY(textEditObject);
 +        QVERIFY(textEditPrivate);
 +        QVERIFY(textEditPrivate->control);
-         QCOMPARE(textEditPrivate->color, pal.color(QPalette::Text));
 +        QCOMPARE(textEditPrivate->color, QColor("black"));
-         QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
-         QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
 +    }
 +    //test normal
 +    for (int i = 0; i < colorStrings.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +        //qDebug() << "textEditObject: " << textEditObject->color() << "vs. " << QColor(colorStrings.at(i));
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->color(), QColor(colorStrings.at(i)));
 +    }
 +
 +    //test selection
 +    for (int i = 0; i < colorStrings.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->selectionColor(), QColor(colorStrings.at(i)));
 +    }
 +
 +    //test selected text
 +    for (int i = 0; i < colorStrings.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->selectedTextColor(), QColor(colorStrings.at(i)));
 +    }
 +
 +    {
 +        QString colorStr = "#AA001234";
 +        QColor testColor("#001234");
 +        testColor.setAlpha(170);
 +
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  color: \"" + colorStr + "\"; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->color(), testColor);
 +    }
 +}
 +
 +void tst_qquicktextedit::textMargin()
 +{
 +    for (qreal i=0; i<=10; i+=0.3) {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  textMargin: " + QString::number(i) + "; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->textMargin(), i);
 +    }
 +}
 +
 +void tst_qquicktextedit::persistentSelection()
 +{
 +    QQuickView canvas(testFileUrl("persistentSelection.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +    canvas.requestActivateWindow();
 +
 +    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
 +    QVERIFY(edit);
 +    QVERIFY(edit->hasActiveFocus());
 +
 +    QSignalSpy spy(edit, SIGNAL(persistentSelectionChanged(bool)));
 +
 +    QCOMPARE(edit->persistentSelection(), false);
 +
 +    edit->setPersistentSelection(false);
 +    QCOMPARE(edit->persistentSelection(), false);
 +    QCOMPARE(spy.count(), 0);
 +
 +    edit->select(1, 4);
 +    QCOMPARE(edit->property("selected").toString(), QLatin1String("ell"));
 +
 +    edit->setFocus(false);
 +    QCOMPARE(edit->property("selected").toString(), QString());
 +
 +    edit->setFocus(true);
 +    QCOMPARE(edit->property("selected").toString(), QString());
 +
 +    edit->setPersistentSelection(true);
 +    QCOMPARE(edit->persistentSelection(), true);
 +    QCOMPARE(spy.count(), 1);
 +
 +    edit->select(1, 4);
 +    QCOMPARE(edit->property("selected").toString(), QLatin1String("ell"));
 +
 +    edit->setFocus(false);
 +    QCOMPARE(edit->property("selected").toString(), QLatin1String("ell"));
 +
 +    edit->setFocus(true);
 +    QCOMPARE(edit->property("selected").toString(), QLatin1String("ell"));
 +
 +}
 +
 +void tst_qquicktextedit::focusOnPress()
 +{
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  activeFocusOnPress: true; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->focusOnPress(), true);
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextEdit {  activeFocusOnPress: false; text: \"Hello World\" }";
 +        QQmlComponent texteditComponent(&engine);
 +        texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +        QVERIFY(textEditObject != 0);
 +        QCOMPARE(textEditObject->focusOnPress(), false);
 +    }
 +}
 +
 +void tst_qquicktextedit::selection()
 +{
 +    QString testStr = standard[0];//TODO: What should happen for multiline/rich text?
 +    QString componentStr = "import QtQuick 2.0\nTextEdit {  text: \""+ testStr +"\"; }";
 +    QQmlComponent texteditComponent(&engine);
 +    texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +    QVERIFY(textEditObject != 0);
 +
 +
 +    //Test selection follows cursor
 +    for (int i=0; i<= testStr.size(); i++) {
 +        textEditObject->setCursorPosition(i);
 +        QCOMPARE(textEditObject->cursorPosition(), i);
 +        QCOMPARE(textEditObject->selectionStart(), i);
 +        QCOMPARE(textEditObject->selectionEnd(), i);
 +        QVERIFY(textEditObject->selectedText().isNull());
 +    }
 +
 +    textEditObject->setCursorPosition(0);
 +    QVERIFY(textEditObject->cursorPosition() == 0);
 +    QVERIFY(textEditObject->selectionStart() == 0);
 +    QVERIFY(textEditObject->selectionEnd() == 0);
 +    QVERIFY(textEditObject->selectedText().isNull());
 +
 +    // Verify invalid positions are ignored.
 +    textEditObject->setCursorPosition(-1);
 +    QVERIFY(textEditObject->cursorPosition() == 0);
 +    QVERIFY(textEditObject->selectionStart() == 0);
 +    QVERIFY(textEditObject->selectionEnd() == 0);
 +    QVERIFY(textEditObject->selectedText().isNull());
 +
 +    textEditObject->setCursorPosition(textEditObject->text().count()+1);
 +    QVERIFY(textEditObject->cursorPosition() == 0);
 +    QVERIFY(textEditObject->selectionStart() == 0);
 +    QVERIFY(textEditObject->selectionEnd() == 0);
 +    QVERIFY(textEditObject->selectedText().isNull());
 +
 +    //Test selection
 +    for (int i=0; i<= testStr.size(); i++) {
 +        textEditObject->select(0,i);
 +        QCOMPARE(testStr.mid(0,i), textEditObject->selectedText());
 +    }
 +    for (int i=0; i<= testStr.size(); i++) {
 +        textEditObject->select(i,testStr.size());
 +        QCOMPARE(testStr.mid(i,testStr.size()-i), textEditObject->selectedText());
 +    }
 +
 +    textEditObject->setCursorPosition(0);
 +    QVERIFY(textEditObject->cursorPosition() == 0);
 +    QVERIFY(textEditObject->selectionStart() == 0);
 +    QVERIFY(textEditObject->selectionEnd() == 0);
 +    QVERIFY(textEditObject->selectedText().isNull());
 +
 +    //Test Error Ignoring behaviour
 +    textEditObject->setCursorPosition(0);
 +    QVERIFY(textEditObject->selectedText().isNull());
 +    textEditObject->select(-10,0);
 +    QVERIFY(textEditObject->selectedText().isNull());
 +    textEditObject->select(100,101);
 +    QVERIFY(textEditObject->selectedText().isNull());
 +    textEditObject->select(0,-10);
 +    QVERIFY(textEditObject->selectedText().isNull());
 +    textEditObject->select(0,100);
 +    QVERIFY(textEditObject->selectedText().isNull());
 +    textEditObject->select(0,10);
 +    QVERIFY(textEditObject->selectedText().size() == 10);
 +    textEditObject->select(-10,0);
 +    QVERIFY(textEditObject->selectedText().size() == 10);
 +    textEditObject->select(100,101);
 +    QVERIFY(textEditObject->selectedText().size() == 10);
 +    textEditObject->select(0,-10);
 +    QVERIFY(textEditObject->selectedText().size() == 10);
 +    textEditObject->select(0,100);
 +    QVERIFY(textEditObject->selectedText().size() == 10);
 +
 +    textEditObject->deselect();
 +    QVERIFY(textEditObject->selectedText().isNull());
 +    textEditObject->select(0,10);
 +    QVERIFY(textEditObject->selectedText().size() == 10);
 +    textEditObject->deselect();
 +    QVERIFY(textEditObject->selectedText().isNull());
 +}
 +
 +void tst_qquicktextedit::isRightToLeft_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<bool>("emptyString");
 +    QTest::addColumn<bool>("firstCharacter");
 +    QTest::addColumn<bool>("lastCharacter");
 +    QTest::addColumn<bool>("middleCharacter");
 +    QTest::addColumn<bool>("startString");
 +    QTest::addColumn<bool>("midString");
 +    QTest::addColumn<bool>("endString");
 +
 +    const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
 +    QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
 +    QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
 +    QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
 +    QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
 +    QTest::newRow("Bidi RTL + LTR + RTL") << QString::fromUtf16(arabic_str, 11) + QString("Hello world") + QString::fromUtf16(arabic_str, 11) << false << true << true << false << true << true << true;
 +    QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
 +}
 +
 +void tst_qquicktextedit::isRightToLeft()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(bool, emptyString);
 +    QFETCH(bool, firstCharacter);
 +    QFETCH(bool, lastCharacter);
 +    QFETCH(bool, middleCharacter);
 +    QFETCH(bool, startString);
 +    QFETCH(bool, midString);
 +    QFETCH(bool, endString);
 +
 +    QQuickTextEdit textEdit;
 +    textEdit.setText(text);
 +
 +    // first test that the right string is delivered to the QString::isRightToLeft()
 +    QCOMPARE(textEdit.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
 +    QCOMPARE(textEdit.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
 +    QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
 +    QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
 +    QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
 +    QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
 +    if (text.isEmpty())
 +        QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start.");
 +    QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
 +
 +    // then test that the feature actually works
 +    QCOMPARE(textEdit.isRightToLeft(0,0), emptyString);
 +    QCOMPARE(textEdit.isRightToLeft(0,1), firstCharacter);
 +    QCOMPARE(textEdit.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
 +    QCOMPARE(textEdit.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
 +    QCOMPARE(textEdit.isRightToLeft(0,text.count()/4), startString);
 +    QCOMPARE(textEdit.isRightToLeft(text.count()/4,3*text.count()/4), midString);
 +    if (text.isEmpty())
 +        QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextEdit: isRightToLeft(start, end) called with the end property being smaller than the start.");
 +    QCOMPARE(textEdit.isRightToLeft(3*text.count()/4,text.count()-1), endString);
 +}
 +
 +void tst_qquicktextedit::keySelection()
 +{
 +    QQuickView canvas(testFileUrl("navigation.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +    canvas.requestActivateWindow();
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +
 +    QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
 +
 +    QVERIFY(input != 0);
 +    QTRY_VERIFY(input->hasActiveFocus() == true);
 +
 +    QSignalSpy spy(input, SIGNAL(selectionChanged()));
 +
 +    simulateKey(&canvas, Qt::Key_Right, Qt::ShiftModifier);
 +    QVERIFY(input->hasActiveFocus() == true);
 +    QCOMPARE(input->selectedText(), QString("a"));
 +    QCOMPARE(spy.count(), 1);
 +    simulateKey(&canvas, Qt::Key_Right);
 +    QVERIFY(input->hasActiveFocus() == true);
 +    QCOMPARE(input->selectedText(), QString());
 +    QCOMPARE(spy.count(), 2);
 +    simulateKey(&canvas, Qt::Key_Right);
 +    QVERIFY(input->hasActiveFocus() == false);
 +    QCOMPARE(input->selectedText(), QString());
 +    QCOMPARE(spy.count(), 2);
 +
 +    simulateKey(&canvas, Qt::Key_Left);
 +    QVERIFY(input->hasActiveFocus() == true);
 +    QCOMPARE(spy.count(), 2);
 +    simulateKey(&canvas, Qt::Key_Left, Qt::ShiftModifier);
 +    QVERIFY(input->hasActiveFocus() == true);
 +    QCOMPARE(input->selectedText(), QString("a"));
 +    QCOMPARE(spy.count(), 3);
 +    simulateKey(&canvas, Qt::Key_Left);
 +    QVERIFY(input->hasActiveFocus() == true);
 +    QCOMPARE(input->selectedText(), QString());
 +    QCOMPARE(spy.count(), 4);
 +    simulateKey(&canvas, Qt::Key_Left);
 +    QVERIFY(input->hasActiveFocus() == false);
 +    QCOMPARE(input->selectedText(), QString());
 +    QCOMPARE(spy.count(), 4);
 +}
 +
 +void tst_qquicktextedit::moveCursorSelection_data()
 +{
 +    QTest::addColumn<QString>("testStr");
 +    QTest::addColumn<int>("cursorPosition");
 +    QTest::addColumn<int>("movePosition");
 +    QTest::addColumn<QQuickTextEdit::SelectionMode>("mode");
 +    QTest::addColumn<int>("selectionStart");
 +    QTest::addColumn<int>("selectionEnd");
 +    QTest::addColumn<bool>("reversible");
 +
 +    QTest::newRow("(t)he|characters")
 +            << standard[0] << 0 << 1 << QQuickTextEdit::SelectCharacters << 0 << 1 << true;
 +    QTest::newRow("do(g)|characters")
 +            << standard[0] << 43 << 44 << QQuickTextEdit::SelectCharacters << 43 << 44 << true;
 +    QTest::newRow("jum(p)ed|characters")
 +            << standard[0] << 23 << 24 << QQuickTextEdit::SelectCharacters << 23 << 24 << true;
 +    QTest::newRow("jumped( )over|characters")
 +            << standard[0] << 26 << 27 << QQuickTextEdit::SelectCharacters << 26 << 27 << true;
 +    QTest::newRow("(the )|characters")
 +            << standard[0] << 0 << 4 << QQuickTextEdit::SelectCharacters << 0 << 4 << true;
 +    QTest::newRow("( dog)|characters")
 +            << standard[0] << 40 << 44 << QQuickTextEdit::SelectCharacters << 40 << 44 << true;
 +    QTest::newRow("( jumped )|characters")
 +            << standard[0] << 19 << 27 << QQuickTextEdit::SelectCharacters << 19 << 27 << true;
 +    QTest::newRow("th(e qu)ick|characters")
 +            << standard[0] << 2 << 6 << QQuickTextEdit::SelectCharacters << 2 << 6 << true;
 +    QTest::newRow("la(zy d)og|characters")
 +            << standard[0] << 38 << 42 << QQuickTextEdit::SelectCharacters << 38 << 42 << true;
 +    QTest::newRow("jum(ped ov)er|characters")
 +            << standard[0] << 23 << 29 << QQuickTextEdit::SelectCharacters << 23 << 29 << true;
 +    QTest::newRow("()the|characters")
 +            << standard[0] << 0 << 0 << QQuickTextEdit::SelectCharacters << 0 << 0 << true;
 +    QTest::newRow("dog()|characters")
 +            << standard[0] << 44 << 44 << QQuickTextEdit::SelectCharacters << 44 << 44 << true;
 +    QTest::newRow("jum()ped|characters")
 +            << standard[0] << 23 << 23 << QQuickTextEdit::SelectCharacters << 23 << 23 << true;
 +
 +    QTest::newRow("<(t)he>|words")
 +            << standard[0] << 0 << 1 << QQuickTextEdit::SelectWords << 0 << 3 << true;
 +    QTest::newRow("<do(g)>|words")
 +            << standard[0] << 43 << 44 << QQuickTextEdit::SelectWords << 41 << 44 << true;
 +    QTest::newRow("<jum(p)ed>|words")
 +            << standard[0] << 23 << 24 << QQuickTextEdit::SelectWords << 20 << 26 << true;
 +    QTest::newRow("<jumped( )>over|words")
 +            << standard[0] << 26 << 27 << QQuickTextEdit::SelectWords << 20 << 27 << false;
 +    QTest::newRow("jumped<( )over>|words,reversed")
 +            << standard[0] << 27 << 26 << QQuickTextEdit::SelectWords << 26 << 31 << false;
 +    QTest::newRow("<(the )>quick|words")
 +            << standard[0] << 0 << 4 << QQuickTextEdit::SelectWords << 0 << 4 << false;
 +    QTest::newRow("<(the )quick>|words,reversed")
 +            << standard[0] << 4 << 0 << QQuickTextEdit::SelectWords << 0 << 9 << false;
 +    QTest::newRow("<lazy( dog)>|words")
 +            << standard[0] << 40 << 44 << QQuickTextEdit::SelectWords << 36 << 44 << false;
 +    QTest::newRow("lazy<( dog)>|words,reversed")
 +            << standard[0] << 44 << 40 << QQuickTextEdit::SelectWords << 40 << 44 << false;
 +    QTest::newRow("<fox( jumped )>over|words")
 +            << standard[0] << 19 << 27 << QQuickTextEdit::SelectWords << 16 << 27 << false;
 +    QTest::newRow("fox<( jumped )over>|words,reversed")
 +            << standard[0] << 27 << 19 << QQuickTextEdit::SelectWords << 19 << 31 << false;
 +    QTest::newRow("<th(e qu)ick>|words")
 +            << standard[0] << 2 << 6 << QQuickTextEdit::SelectWords << 0 << 9 << true;
 +    QTest::newRow("<la(zy d)og|words>")
 +            << standard[0] << 38 << 42 << QQuickTextEdit::SelectWords << 36 << 44 << true;
 +    QTest::newRow("<jum(ped ov)er>|words")
 +            << standard[0] << 23 << 29 << QQuickTextEdit::SelectWords << 20 << 31 << true;
 +    QTest::newRow("<()>the|words")
 +            << standard[0] << 0 << 0 << QQuickTextEdit::SelectWords << 0 << 0 << true;
 +    QTest::newRow("dog<()>|words")
 +            << standard[0] << 44 << 44 << QQuickTextEdit::SelectWords << 44 << 44 << true;
 +    QTest::newRow("jum<()>ped|words")
 +            << standard[0] << 23 << 23 << QQuickTextEdit::SelectWords << 23 << 23 << true;
 +
 +    QTest::newRow("Hello<(,)> |words")
 +            << standard[2] << 5 << 6 << QQuickTextEdit::SelectWords << 5 << 6 << true;
 +    QTest::newRow("Hello<(, )>world|words")
 +            << standard[2] << 5 << 7 << QQuickTextEdit::SelectWords << 5 << 7 << false;
 +    QTest::newRow("Hello<(, )world>|words,reversed")
 +            << standard[2] << 7 << 5 << QQuickTextEdit::SelectWords << 5 << 12 << false;
 +    QTest::newRow("<Hel(lo, )>world|words")
 +            << standard[2] << 3 << 7 << QQuickTextEdit::SelectWords << 0 << 7 << false;
 +    QTest::newRow("<Hel(lo, )world>|words,reversed")
 +            << standard[2] << 7 << 3 << QQuickTextEdit::SelectWords << 0 << 12 << false;
 +    QTest::newRow("<Hel(lo)>,|words")
 +            << standard[2] << 3 << 5 << QQuickTextEdit::SelectWords << 0 << 5 << true;
 +    QTest::newRow("Hello<()>,|words")
 +            << standard[2] << 5 << 5 << QQuickTextEdit::SelectWords << 5 << 5 << true;
 +    QTest::newRow("Hello,<()>|words")
 +            << standard[2] << 6 << 6 << QQuickTextEdit::SelectWords << 6 << 6 << true;
 +    QTest::newRow("Hello<,( )>world|words")
 +            << standard[2] << 6 << 7 << QQuickTextEdit::SelectWords << 5 << 7 << false;
 +    QTest::newRow("Hello,<( )world>|words,reversed")
 +            << standard[2] << 7 << 6 << QQuickTextEdit::SelectWords << 6 << 12 << false;
 +    QTest::newRow("Hello<,( world)>|words")
 +            << standard[2] << 6 << 12 << QQuickTextEdit::SelectWords << 5 << 12 << false;
 +    QTest::newRow("Hello,<( world)>|words,reversed")
 +            << standard[2] << 12 << 6 << QQuickTextEdit::SelectWords << 6 << 12 << false;
 +    QTest::newRow("Hello<,( world!)>|words")
 +            << standard[2] << 6 << 13 << QQuickTextEdit::SelectWords << 5 << 13 << false;
 +    QTest::newRow("Hello,<( world!)>|words,reversed")
 +            << standard[2] << 13 << 6 << QQuickTextEdit::SelectWords << 6 << 13 << false;
 +    QTest::newRow("Hello<(, world!)>|words")
 +            << standard[2] << 5 << 13 << QQuickTextEdit::SelectWords << 5 << 13 << true;
 +    QTest::newRow("world<(!)>|words")
 +            << standard[2] << 12 << 13 << QQuickTextEdit::SelectWords << 12 << 13 << true;
 +    QTest::newRow("world!<()>)|words")
 +            << standard[2] << 13 << 13 << QQuickTextEdit::SelectWords << 13 << 13 << true;
 +    QTest::newRow("world<()>!)|words")
 +            << standard[2] << 12 << 12 << QQuickTextEdit::SelectWords << 12 << 12 << true;
 +
 +    QTest::newRow("<(,)>olleH |words")
 +            << standard[3] << 7 << 8 << QQuickTextEdit::SelectWords << 7 << 8 << true;
 +    QTest::newRow("<dlrow( ,)>olleH|words")
 +            << standard[3] << 6 << 8 << QQuickTextEdit::SelectWords << 1 << 8 << false;
 +    QTest::newRow("dlrow<( ,)>olleH|words,reversed")
 +            << standard[3] << 8 << 6 << QQuickTextEdit::SelectWords << 6 << 8 << false;
 +    QTest::newRow("<dlrow( ,ol)leH>|words")
 +            << standard[3] << 6 << 10 << QQuickTextEdit::SelectWords << 1 << 13 << false;
 +    QTest::newRow("dlrow<( ,ol)leH>|words,reversed")
 +            << standard[3] << 10 << 6 << QQuickTextEdit::SelectWords << 6 << 13 << false;
 +    QTest::newRow(",<(ol)leH>,|words")
 +            << standard[3] << 8 << 10 << QQuickTextEdit::SelectWords << 8 << 13 << true;
 +    QTest::newRow(",<()>olleH|words")
 +            << standard[3] << 8 << 8 << QQuickTextEdit::SelectWords << 8 << 8 << true;
 +    QTest::newRow("<()>,olleH|words")
 +            << standard[3] << 7 << 7 << QQuickTextEdit::SelectWords << 7 << 7 << true;
 +    QTest::newRow("<dlrow( )>,olleH|words")
 +            << standard[3] << 6 << 7 << QQuickTextEdit::SelectWords << 1 << 7 << false;
 +    QTest::newRow("dlrow<( ),>olleH|words,reversed")
 +            << standard[3] << 7 << 6 << QQuickTextEdit::SelectWords << 6 << 8 << false;
 +    QTest::newRow("<(dlrow )>,olleH|words")
 +            << standard[3] << 1 << 7 << QQuickTextEdit::SelectWords << 1 << 7 << false;
 +    QTest::newRow("<(dlrow ),>olleH|words,reversed")
 +            << standard[3] << 7 << 1 << QQuickTextEdit::SelectWords << 1 << 8 << false;
 +    QTest::newRow("<(!dlrow )>,olleH|words")
 +            << standard[3] << 0 << 7 << QQuickTextEdit::SelectWords << 0 << 7 << false;
 +    QTest::newRow("<(!dlrow ),>olleH|words,reversed")
 +            << standard[3] << 7 << 0 << QQuickTextEdit::SelectWords << 0 << 8 << false;
 +    QTest::newRow("(!dlrow ,)olleH|words")
 +            << standard[3] << 0 << 8 << QQuickTextEdit::SelectWords << 0 << 8 << true;
 +    QTest::newRow("<(!)>dlrow|words")
 +            << standard[3] << 0 << 1 << QQuickTextEdit::SelectWords << 0 << 1 << true;
 +    QTest::newRow("<()>!dlrow|words")
 +            << standard[3] << 0 << 0 << QQuickTextEdit::SelectWords << 0 << 0 << true;
 +    QTest::newRow("!<()>dlrow|words")
 +            << standard[3] << 1 << 1 << QQuickTextEdit::SelectWords << 1 << 1 << true;
 +}
 +
 +void tst_qquicktextedit::moveCursorSelection()
 +{
 +    QFETCH(QString, testStr);
 +    QFETCH(int, cursorPosition);
 +    QFETCH(int, movePosition);
 +    QFETCH(QQuickTextEdit::SelectionMode, mode);
 +    QFETCH(int, selectionStart);
 +    QFETCH(int, selectionEnd);
 +    QFETCH(bool, reversible);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit {  text: \""+ testStr +"\"; }";
 +    QQmlComponent textinputComponent(&engine);
 +    textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit*>(textinputComponent.create());
 +    QVERIFY(texteditObject != 0);
 +
 +    texteditObject->setCursorPosition(cursorPosition);
 +    texteditObject->moveCursorSelection(movePosition, mode);
 +
 +    QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
 +    QCOMPARE(texteditObject->selectionStart(), selectionStart);
 +    QCOMPARE(texteditObject->selectionEnd(), selectionEnd);
 +
 +    if (reversible) {
 +        texteditObject->setCursorPosition(movePosition);
 +        texteditObject->moveCursorSelection(cursorPosition, mode);
 +
 +        QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
 +        QCOMPARE(texteditObject->selectionStart(), selectionStart);
 +        QCOMPARE(texteditObject->selectionEnd(), selectionEnd);
 +    }
 +}
 +
 +void tst_qquicktextedit::moveCursorSelectionSequence_data()
 +{
 +    QTest::addColumn<QString>("testStr");
 +    QTest::addColumn<int>("cursorPosition");
 +    QTest::addColumn<int>("movePosition1");
 +    QTest::addColumn<int>("movePosition2");
 +    QTest::addColumn<int>("selection1Start");
 +    QTest::addColumn<int>("selection1End");
 +    QTest::addColumn<int>("selection2Start");
 +    QTest::addColumn<int>("selection2End");
 +
 +    QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
 +            << standard[0]
 +            << 9 << 13 << 17
 +            << 4 << 15
 +            << 4 << 19;
 +    QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
 +            << standard[0]
 +            << 13 << 9 << 17
 +            << 9 << 15
 +            << 10 << 19;
 +    QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
 +            << standard[0]
 +            << 9 << 13 << 16
 +            << 4 << 15
 +            << 4 << 16;
 +    QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
 +            << standard[0]
 +            << 13 << 9 << 16
 +            << 9 << 15
 +            << 10 << 16;
 +    QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
 +            << standard[0]
 +            << 9 << 13 << 15
 +            << 4 << 15
 +            << 4 << 15;
 +    QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
 +            << standard[0]
 +            << 13 << 9 << 15
 +            << 9 << 15
 +            << 10 << 15;
 +    QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 10
 +            << 4 << 15
 +            << 4 << 10;
 +    QTest::newRow("the quick<(^ {^bro)wn>} fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 10
 +            << 9 << 15
 +            << 10 << 15;
 +    QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 9
 +            << 4 << 15
 +            << 4 << 9;
 +    QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 9
 +            << 9 << 15
 +            << 9 << 15;
 +    QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 7
 +            << 4 << 15
 +            << 4 << 9;
 +    QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 7
 +            << 9 << 15
 +            << 4 << 15;
 +    QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 4
 +            << 4 << 15
 +            << 4 << 9;
 +    QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 4
 +            << 9 << 15
 +            << 4 << 15;
 +    QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 3
 +            << 4 << 15
 +            << 3 << 9;
 +    QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 3
 +            << 9 << 15
 +            << 3 << 15;
 +    QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 1
 +            << 4 << 15
 +            << 0 << 9;
 +    QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 1
 +            << 9 << 15
 +            << 0 << 15;
 +
 +    QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
 +            << standard[2]
 +            << 2 << 4 << 8
 +            << 0 << 5
 +            << 0 << 12;
 +    QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
 +            << standard[2]
 +            << 4 << 2 << 8
 +            << 0 << 5
 +            << 0 << 12;
 +
 +    QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
 +            << standard[3]
 +            << 9 << 11 << 5
 +            << 8 << 13
 +            << 1 << 13;
 +    QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
 +            << standard[3]
 +            << 11 << 9 << 5
 +            << 8 << 13
 +            << 1 << 13;
 +}
 +
 +void tst_qquicktextedit::moveCursorSelectionSequence()
 +{
 +    QFETCH(QString, testStr);
 +    QFETCH(int, cursorPosition);
 +    QFETCH(int, movePosition1);
 +    QFETCH(int, movePosition2);
 +    QFETCH(int, selection1Start);
 +    QFETCH(int, selection1End);
 +    QFETCH(int, selection2Start);
 +    QFETCH(int, selection2End);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit {  text: \""+ testStr +"\"; }";
 +    QQmlComponent texteditComponent(&engine);
 +    texteditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 +    QVERIFY(texteditObject != 0);
 +
 +    texteditObject->setCursorPosition(cursorPosition);
 +
 +    texteditObject->moveCursorSelection(movePosition1, QQuickTextEdit::SelectWords);
 +    QCOMPARE(texteditObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
 +    QCOMPARE(texteditObject->selectionStart(), selection1Start);
 +    QCOMPARE(texteditObject->selectionEnd(), selection1End);
 +
 +    texteditObject->moveCursorSelection(movePosition2, QQuickTextEdit::SelectWords);
 +    QCOMPARE(texteditObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
 +    QCOMPARE(texteditObject->selectionStart(), selection2Start);
 +    QCOMPARE(texteditObject->selectionEnd(), selection2End);
 +}
 +
 +
 +void tst_qquicktextedit::mouseSelection_data()
 +{
 +    QTest::addColumn<QString>("qmlfile");
 +    QTest::addColumn<int>("from");
 +    QTest::addColumn<int>("to");
 +    QTest::addColumn<QString>("selectedText");
 +
 +    // import installed
 +    QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678";
 +    QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString();
 +    QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString();
 +    QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString();
 +    QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789";
 +    QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +    QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +    QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +    QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +    QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +    QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +    QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +    QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +}
 +
 +void tst_qquicktextedit::mouseSelection()
 +{
 +    QFETCH(QString, qmlfile);
 +    QFETCH(int, from);
 +    QFETCH(int, to);
 +    QFETCH(QString, selectedText);
 +
 +    QQuickView canvas(QUrl::fromLocalFile(qmlfile));
 +
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
 +    QVERIFY(textEditObject != 0);
 +
 +    // press-and-drag-and-release from x1 to x2
 +    QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint();
 +    QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint();
 +    QTest::mousePress(&canvas, Qt::LeftButton, 0, p1);
 +    QTest::mouseMove(&canvas, p2);
 +    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, p2);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(textEditObject->selectedText(), selectedText);
 +
 +    // Clicking and shift to clicking between the same points should select the same text.
 +    textEditObject->setCursorPosition(0);
 +    QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, p1);
 +    QTest::mouseClick(&canvas, Qt::LeftButton, Qt::ShiftModifier, p2);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(textEditObject->selectedText(), selectedText);
 +}
 +
 +void tst_qquicktextedit::dragMouseSelection()
 +{
 +    QString qmlfile = testFile("mouseselection_true.qml");
 +
 +    QQuickView canvas(QUrl::fromLocalFile(qmlfile));
 +
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
 +    QVERIFY(textEditObject != 0);
 +
 +    // press-and-drag-and-release from x1 to x2
 +    int x1 = 10;
 +    int x2 = 70;
 +    int y = textEditObject->height()/2;
 +    QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
 +    QTest::mouseMove(&canvas, QPoint(x2, y));
 +    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
 +    QTest::qWait(300);
 +    QString str1;
 +    QTRY_VERIFY((str1 = textEditObject->selectedText()).length() > 3);
 +
 +    // press and drag the current selection.
 +    x1 = 40;
 +    x2 = 100;
 +    QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
 +    QTest::mouseMove(&canvas, QPoint(x2, y));
 +    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
 +    QTest::qWait(300);
 +    QString str2;
 +    QTRY_VERIFY((str2 = textEditObject->selectedText()).length() > 3);
 +
 +    QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and not the first moved.
 +}
 +
 +void tst_qquicktextedit::mouseSelectionMode_data()
 +{
 +    QTest::addColumn<QString>("qmlfile");
 +    QTest::addColumn<bool>("selectWords");
 +
 +    // import installed
 +    QTest::newRow("SelectWords") << testFile("mouseselectionmode_words.qml") << true;
 +    QTest::newRow("SelectCharacters") << testFile("mouseselectionmode_characters.qml") << false;
 +    QTest::newRow("default") << testFile("mouseselectionmode_default.qml") << false;
 +}
 +
 +void tst_qquicktextedit::mouseSelectionMode()
 +{
 +    QFETCH(QString, qmlfile);
 +    QFETCH(bool, selectWords);
 +
 +    QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +
 +    QQuickView canvas(QUrl::fromLocalFile(qmlfile));
 +
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
 +    QVERIFY(textEditObject != 0);
 +
 +    // press-and-drag-and-release from x1 to x2
 +    int x1 = 10;
 +    int x2 = 70;
 +    int y = textEditObject->height()/2;
 +    QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
 +    QTest::mouseMove(&canvas, QPoint(x2, y));
 +    //QTest::mouseMove(canvas, QPoint(x2,y)); // doesn't work
 +//    QMouseEvent mv(QEvent::MouseMove, QPoint(x2,y), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
 +//    QGuiApplication::sendEvent(&canvas, &mv);
 +    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
 +    QString str = textEditObject->selectedText();
 +    if (selectWords) {
 +        QTRY_COMPARE(textEditObject->selectedText(), text);
 +    } else {
 +        QTRY_VERIFY(textEditObject->selectedText().length() > 3);
 +        QVERIFY(str != text);
 +    }
 +}
 +
 +void tst_qquicktextedit::inputMethodHints()
 +{
 +    QQuickView canvas(testFileUrl("inputmethodhints.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
 +    QVERIFY(textEditObject != 0);
 +    QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
 +    QSignalSpy inputMethodHintSpy(textEditObject, SIGNAL(inputMethodHintsChanged()));
 +    textEditObject->setInputMethodHints(Qt::ImhUppercaseOnly);
 +    QVERIFY(textEditObject->inputMethodHints() & Qt::ImhUppercaseOnly);
 +    QCOMPARE(inputMethodHintSpy.count(), 1);
 +    textEditObject->setInputMethodHints(Qt::ImhUppercaseOnly);
 +    QCOMPARE(inputMethodHintSpy.count(), 1);
 +
 +    QQuickTextEdit plainTextEdit;
 +    QCOMPARE(plainTextEdit.inputMethodHints(), Qt::ImhNone);
 +}
 +
 +void tst_qquicktextedit::positionAt()
 +{
 +    QQuickView canvas(testFileUrl("positionAt.qml"));
 +    QVERIFY(canvas.rootObject() != 0);
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +
 +    QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
 +    QVERIFY(texteditObject != 0);
 +
 +    QTextLayout layout(texteditObject->text());
 +    layout.setFont(texteditObject->font());
 +
 +    if (!qmlDisableDistanceField()) {
 +        QTextOption option;
 +        option.setUseDesignMetrics(true);
 +        layout.setTextOption(option);
 +    }
 +
 +    layout.beginLayout();
 +    QTextLine line = layout.createLine();
 +    layout.endLayout();
 +
 +    const int y0 = line.height() / 2;
 +    const int y1 = line.height() * 3 / 2;
 +
 +    int pos = texteditObject->positionAt(texteditObject->width()/2, y0);
 +
 +    int widthBegin = floor(line.cursorToX(pos - 1));
 +    int widthEnd = ceil(line.cursorToX(pos + 1));
 +
 +    QVERIFY(widthBegin <= texteditObject->width() / 2);
 +    QVERIFY(widthEnd >= texteditObject->width() / 2);
 +
 +    const qreal x0 = texteditObject->positionToRectangle(pos).x();
 +    const qreal x1 = texteditObject->positionToRectangle(pos + 1).x();
 +
 +    QString preeditText = texteditObject->text().mid(0, pos);
 +    texteditObject->setText(texteditObject->text().mid(pos));
 +    texteditObject->setCursorPosition(0);
 +
 +    QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
 +    QGuiApplication::sendEvent(qGuiApp->focusObject(), &inputEvent);
 +
 +    // Check all points within the preedit text return the same position.
 +    QCOMPARE(texteditObject->positionAt(0, y0), 0);
 +    QCOMPARE(texteditObject->positionAt(x0 / 2, y0), 0);
 +    QCOMPARE(texteditObject->positionAt(x0, y0), 0);
 +
 +    // Verify positioning returns to normal after the preedit text.
 +    QCOMPARE(texteditObject->positionAt(x1, y0), 1);
 +    QCOMPARE(texteditObject->positionToRectangle(1).x(), x1);
 +
 +    QVERIFY(texteditObject->positionAt(x0 / 2, y1) > 0);
 +}
 +
 +void tst_qquicktextedit::linkActivated()
 +{
 +    QQuickView canvas(testFileUrl("linkActivated.qml"));
 +    QVERIFY(canvas.rootObject() != 0);
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +
 +    QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
 +    QVERIFY(texteditObject != 0);
 +
 +    QSignalSpy spy(texteditObject, SIGNAL(linkActivated(QString)));
 +
 +    const QString link("http://example.com/");
 +
 +    const QPointF linkPos = texteditObject->positionToRectangle(7).center();
 +    const QPointF textPos = texteditObject->positionToRectangle(2).center();
 +
 +    QTest::mouseClick(&canvas, Qt::LeftButton, 0, linkPos.toPoint());
 +    QTRY_COMPARE(spy.count(), 1);
 +    QCOMPARE(spy.last()[0].toString(), link);
 +
 +    QTest::mouseClick(&canvas, Qt::LeftButton, 0, textPos.toPoint());
 +    QTest::qWait(50);
 +    QCOMPARE(spy.count(), 1);
 +
 +    texteditObject->setReadOnly(true);
 +
 +    QTest::mouseClick(&canvas, Qt::LeftButton, 0, linkPos.toPoint());
 +    QTRY_COMPARE(spy.count(), 2);
 +    QCOMPARE(spy.last()[0].toString(), link);
 +
 +    QTest::mouseClick(&canvas, Qt::LeftButton, 0, textPos.toPoint());
 +    QTest::qWait(50);
 +    QCOMPARE(spy.count(), 2);
 +}
 +
 +void tst_qquicktextedit::cursorDelegate_data()
 +{
 +    QTest::addColumn<QUrl>("source");
 +    QTest::newRow("out of line") << testFileUrl("cursorTest.qml");
 +    QTest::newRow("in line") << testFileUrl("cursorTestInline.qml");
 +    QTest::newRow("external") << testFileUrl("cursorTestExternal.qml");
 +}
 +
 +void tst_qquicktextedit::cursorDelegate()
 +{
 +    QFETCH(QUrl, source);
 +    QQuickView view(source);
 +    view.show();
 +    view.requestActivateWindow();
 +    QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
 +    QVERIFY(textEditObject != 0);
 +    QVERIFY(textEditObject->findChild<QQuickItem*>("cursorInstance"));
 +    //Test Delegate gets created
 +    textEditObject->setFocus(true);
 +    QQuickItem* delegateObject = textEditObject->findChild<QQuickItem*>("cursorInstance");
 +    QVERIFY(delegateObject);
 +    QCOMPARE(delegateObject->property("localProperty").toString(), QString("Hello"));
 +    //Test Delegate gets moved
 +    for (int i=0; i<= textEditObject->text().length(); i++) {
 +        textEditObject->setCursorPosition(i);
-     QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
-     QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
++        QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
++        QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
 +    }
 +    // Clear preedit text;
 +    QInputMethodEvent event;
 +    QGuiApplication::sendEvent(&view, &event);
 +
 +
 +    // Test delegate gets moved on mouse press.
 +    textEditObject->setSelectByMouse(true);
 +    textEditObject->setCursorPosition(0);
 +    const QPoint point1 = textEditObject->positionToRectangle(5).center().toPoint();
 +    QTest::mouseClick(&view, Qt::LeftButton, 0, point1);
 +    QTest::qWait(50);
 +    QTRY_VERIFY(textEditObject->cursorPosition() != 0);
-     QTRY_COMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
-     QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
++    QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
++    QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
 +
 +    // Test delegate gets moved on mouse drag
 +    textEditObject->setCursorPosition(0);
 +    const QPoint point2 = textEditObject->positionToRectangle(10).center().toPoint();
 +    QTest::mousePress(&view, Qt::LeftButton, 0, point1);
 +    QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
 +    QGuiApplication::sendEvent(&view, &mv);
 +    QTest::mouseRelease(&view, Qt::LeftButton, 0, point2);
 +    QTest::qWait(50);
-     QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
-     QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
++    QTRY_COMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
++    QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
 +
 +    textEditObject->setReadOnly(true);
 +    textEditObject->setCursorPosition(0);
 +    QTest::mouseClick(&view, Qt::LeftButton, 0, textEditObject->positionToRectangle(5).center().toPoint());
 +    QTest::qWait(50);
 +    QTRY_VERIFY(textEditObject->cursorPosition() != 0);
-     QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
-     QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
++    QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
++    QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
 +
 +    textEditObject->setCursorPosition(0);
 +    QTest::mouseClick(&view, Qt::LeftButton, 0, textEditObject->positionToRectangle(5).center().toPoint());
 +    QTest::qWait(50);
 +    QTRY_VERIFY(textEditObject->cursorPosition() != 0);
-     QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x()));
-     QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y()));
++    QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
++    QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
 +
 +    textEditObject->setCursorPosition(0);
-     QRect cursorRectFromItem = textEdit->cursorRectangle();
++    QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
++    QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
 +    //Test Delegate gets deleted
 +    textEditObject->setCursorDelegate(0);
 +    QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
 +}
 +
 +void tst_qquicktextedit::cursorVisible()
 +{
 +    QQuickView view(testFileUrl("cursorVisible.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +
 +    QQuickTextEdit edit;
 +    QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool)));
 +
 +    QCOMPARE(edit.isCursorVisible(), false);
 +
 +    edit.setCursorVisible(true);
 +    QCOMPARE(edit.isCursorVisible(), true);
 +    QCOMPARE(spy.count(), 1);
 +
 +    edit.setCursorVisible(false);
 +    QCOMPARE(edit.isCursorVisible(), false);
 +    QCOMPARE(spy.count(), 2);
 +
 +    edit.setFocus(true);
 +    QCOMPARE(edit.isCursorVisible(), false);
 +    QCOMPARE(spy.count(), 2);
 +
 +    edit.setParentItem(view.rootObject());
 +    QCOMPARE(edit.isCursorVisible(), true);
 +    QCOMPARE(spy.count(), 3);
 +
 +    edit.setFocus(false);
 +    QCOMPARE(edit.isCursorVisible(), false);
 +    QCOMPARE(spy.count(), 4);
 +
 +    edit.setFocus(true);
 +    QCOMPARE(edit.isCursorVisible(), true);
 +    QCOMPARE(spy.count(), 5);
 +
 +    QQuickView alternateView;
 +    alternateView.show();
 +    alternateView.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&alternateView);
 +
 +    QCOMPARE(edit.isCursorVisible(), false);
 +    QCOMPARE(spy.count(), 6);
 +
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QCOMPARE(edit.isCursorVisible(), true);
 +    QCOMPARE(spy.count(), 7);
 +}
 +
 +void tst_qquicktextedit::delegateLoading_data()
 +{
 +    QTest::addColumn<QString>("qmlfile");
 +    QTest::addColumn<QString>("error");
 +
 +    // import installed
 +    QTest::newRow("pass") << "cursorHttpTestPass.qml" << "";
 +    QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "http://localhost:42332/FailItem.qml: Remote host closed the connection ";
 +    QTest::newRow("fail2") << "cursorHttpTestFail2.qml" << "http://localhost:42332/ErrItem.qml:4:5: Fungus is not a type ";
 +}
 +
 +void tst_qquicktextedit::delegateLoading()
 +{
 +#ifdef Q_OS_MAC
 +    QSKIP("Test crashes during canvas tear down. QTBUG-23010");
 +#endif
 +    QFETCH(QString, qmlfile);
 +    QFETCH(QString, error);
 +
 +    TestHTTPServer server(42332);
 +    server.serveDirectory(testFile("httpfail"), TestHTTPServer::Disconnect);
 +    server.serveDirectory(testFile("httpslow"), TestHTTPServer::Delay);
 +    server.serveDirectory(testFile("http"));
 +
 +    QQuickView view(QUrl(QLatin1String("http://localhost:42332/") + qmlfile));
 +    view.show();
 +    view.requestActivateWindow();
 +
 +    if (!error.isEmpty()) {
 +        QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
 +        QTRY_VERIFY(view.status()==QQuickView::Error);
 +        QTRY_VERIFY(!view.rootObject()); // there is fail item inside this test
 +    } else {
 +        QTRY_VERIFY(view.rootObject());//Wait for loading to finish.
 +        QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
 +        //    view.rootObject()->dumpObjectTree();
 +        QVERIFY(textEditObject != 0);
 +        textEditObject->setFocus(true);
 +        QQuickItem *delegate;
 +        delegate = view.rootObject()->findChild<QQuickItem*>("delegateOkay");
 +        QVERIFY(delegate);
 +        delegate = view.rootObject()->findChild<QQuickItem*>("delegateSlow");
 +        QVERIFY(delegate);
 +
 +        delete delegate;
 +    }
 +
 +
 +    //A test should be added here with a component which is ready but component.create() returns null
 +    //Not sure how to accomplish this with QQuickTextEdits cursor delegate
 +    //###This was only needed for code coverage, and could be a case of overzealous defensive programming
 +    //delegate = view.rootObject()->findChild<QQuickItem*>("delegateErrorB");
 +    //QVERIFY(!delegate);
 +}
 +
 +/*
 +TextEdit element should only handle left/right keys until the cursor reaches
 +the extent of the text, then they should ignore the keys.
 +*/
 +void tst_qquicktextedit::navigation()
 +{
 +    QQuickView canvas(testFileUrl("navigation.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +
 +    QQuickItem *input = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
 +
 +    QVERIFY(input != 0);
 +    QTRY_VERIFY(input->hasActiveFocus() == true);
 +    simulateKey(&canvas, Qt::Key_Left);
 +    QVERIFY(input->hasActiveFocus() == false);
 +    simulateKey(&canvas, Qt::Key_Right);
 +    QVERIFY(input->hasActiveFocus() == true);
 +    simulateKey(&canvas, Qt::Key_Right);
 +    QVERIFY(input->hasActiveFocus() == true);
 +    simulateKey(&canvas, Qt::Key_Right);
 +    QVERIFY(input->hasActiveFocus() == false);
 +    simulateKey(&canvas, Qt::Key_Left);
 +    QVERIFY(input->hasActiveFocus() == true);
 +}
 +
 +void tst_qquicktextedit::copyAndPaste() {
 +#ifndef QT_NO_CLIPBOARD
 +
 +#ifdef Q_OS_MAC
 +    {
 +        PasteboardRef pasteboard;
 +        OSStatus status = PasteboardCreate(0, &pasteboard);
 +        if (status == noErr)
 +            CFRelease(pasteboard);
 +        else
 +            QSKIP("This machine doesn't support the clipboard");
 +    }
 +#endif
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    // copy and paste
 +    QCOMPARE(textEdit->text().length(), 12);
 +    textEdit->select(0, textEdit->text().length());;
 +    textEdit->copy();
 +    QCOMPARE(textEdit->selectedText(), QString("Hello world!"));
 +    QCOMPARE(textEdit->selectedText().length(), 12);
 +    textEdit->setCursorPosition(0);
 +    QVERIFY(textEdit->canPaste());
 +    textEdit->paste();
 +    QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
 +    QCOMPARE(textEdit->text().length(), 24);
 +
 +    // canPaste
 +    QVERIFY(textEdit->canPaste());
 +    textEdit->setReadOnly(true);
 +    QVERIFY(!textEdit->canPaste());
 +    textEdit->setReadOnly(false);
 +    QVERIFY(textEdit->canPaste());
 +
 +    // QTBUG-12339
 +    // test that document and internal text attribute are in sync
 +    QQuickItemPrivate* pri = QQuickItemPrivate::get(textEdit);
 +    QQuickTextEditPrivate *editPrivate = static_cast<QQuickTextEditPrivate*>(pri);
 +    QCOMPARE(textEdit->text(), editPrivate->text);
 +
 +    // select word
 +    textEdit->setCursorPosition(0);
 +    textEdit->selectWord();
 +    QCOMPARE(textEdit->selectedText(), QString("Hello"));
 +
 +    // select all and cut
 +    textEdit->selectAll();
 +    textEdit->cut();
 +    QCOMPARE(textEdit->text().length(), 0);
 +    textEdit->paste();
 +    QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
 +    QCOMPARE(textEdit->text().length(), 24);
 +#endif
 +}
 +
 +void tst_qquicktextedit::canPaste() {
 +#ifndef QT_NO_CLIPBOARD
 +
 +    QGuiApplication::clipboard()->setText("Some text");
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    // check initial value - QTBUG-17765
 +    QQuickTextControl tc(0);
 +    QCOMPARE(textEdit->canPaste(), tc.canPaste());
 +
 +#endif
 +}
 +
 +void tst_qquicktextedit::canPasteEmpty() {
 +#ifndef QT_NO_CLIPBOARD
 +
 +    QGuiApplication::clipboard()->clear();
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    // check initial value - QTBUG-17765
 +    QQuickTextControl tc(0);
 +    QCOMPARE(textEdit->canPaste(), tc.canPaste());
 +
 +#endif
 +}
 +
 +void tst_qquicktextedit::readOnly()
 +{
 +    QQuickView canvas(testFileUrl("readOnly.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +
 +    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
 +
 +    QVERIFY(edit != 0);
 +    QTRY_VERIFY(edit->hasActiveFocus() == true);
 +    QVERIFY(edit->isReadOnly() == true);
 +    QString initial = edit->text();
 +    for (int k=Qt::Key_0; k<=Qt::Key_Z; k++)
 +        simulateKey(&canvas, k);
 +    simulateKey(&canvas, Qt::Key_Return);
 +    simulateKey(&canvas, Qt::Key_Space);
 +    simulateKey(&canvas, Qt::Key_Escape);
 +    QCOMPARE(edit->text(), initial);
 +
 +    edit->setCursorPosition(3);
 +    edit->setReadOnly(false);
 +    QCOMPARE(edit->isReadOnly(), false);
 +    QCOMPARE(edit->cursorPosition(), edit->text().length());
 +}
 +
 +void tst_qquicktextedit::simulateKey(QQuickView *view, int key, Qt::KeyboardModifiers modifiers)
 +{
 +    QKeyEvent press(QKeyEvent::KeyPress, key, modifiers);
 +    QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers);
 +
 +    QGuiApplication::sendEvent(view, &press);
 +    QGuiApplication::sendEvent(view, &release);
 +}
 +
 +void tst_qquicktextedit::textInput()
 +{
 +    QQuickView view(testFileUrl("inputMethodEvent.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
 +    QVERIFY(edit);
 +    QVERIFY(edit->hasActiveFocus() == true);
 +
 +    // test that input method event is committed and change signal is emitted
 +    QSignalSpy spy(edit, SIGNAL(textChanged()));
 +    QInputMethodEvent event;
 +    event.setCommitString( "Hello world!", 0, 0);
 +    QGuiApplication::sendEvent(qGuiApp->focusObject(), &event);
 +    QCOMPARE(edit->text(), QString("Hello world!"));
 +    QCOMPARE(spy.count(), 1);
 +
 +    // QTBUG-12339
 +    // test that document and internal text attribute are in sync
 +    QQuickTextEditPrivate *editPrivate = static_cast<QQuickTextEditPrivate*>(QQuickItemPrivate::get(edit));
 +    QCOMPARE(editPrivate->text, QString("Hello world!"));
 +
 +    // test that tentative commit is included in text property
 +    edit->setText("");
 +    spy.clear();
 +    QList<QInputMethodEvent::Attribute> attributes;
 +    QInputMethodEvent event2("preedit", attributes);
 +    event2.setTentativeCommitString("string");
 +    QGuiApplication::sendEvent(qGuiApp->focusObject(), &event2);
 +    QCOMPARE(spy.count(), 1);
 +    QCOMPARE(edit->text(), QString("string"));
 +
 +    QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
 +    QGuiApplication::sendEvent(qGuiApp->focusObject(), &queryEvent);
 +    QCOMPARE(queryEvent.value(Qt::ImEnabled).toBool(), true);
 +
 +    edit->setReadOnly(true);
 +    QGuiApplication::sendEvent(edit, &queryEvent);
 +    QCOMPARE(queryEvent.value(Qt::ImEnabled).toBool(), false);
 +}
 +
 +void tst_qquicktextedit::inputMethodUpdate()
 +{
 +    PlatformInputContext platformInputContext;
 +    QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
 +    inputMethodPrivate->testContext = &platformInputContext;
 +
 +    QQuickView view(testFileUrl("inputMethodEvent.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
 +    QVERIFY(edit);
 +    QVERIFY(edit->hasActiveFocus() == true);
 +
 +    // text change even without cursor position change needs to trigger update
 +    edit->setText("test");
 +    platformInputContext.clear();
 +    edit->setText("xxxx");
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // input method event replacing text
 +    platformInputContext.clear();
 +    {
 +        QInputMethodEvent inputMethodEvent;
 +        inputMethodEvent.setCommitString("y", -1, 1);
 +        QGuiApplication::sendEvent(edit, &inputMethodEvent);
 +    }
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // input method changing selection
 +    platformInputContext.clear();
 +    {
 +        QList<QInputMethodEvent::Attribute> attributes;
 +        attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 2, QVariant());
 +        QInputMethodEvent inputMethodEvent("", attributes);
 +        QGuiApplication::sendEvent(edit, &inputMethodEvent);
 +    }
 +    QVERIFY(edit->selectionStart() != edit->selectionEnd());
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // font changes
 +    platformInputContext.clear();
 +    QFont font = edit->font();
 +    font.setBold(!font.bold());
 +    edit->setFont(font);
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // normal input
 +    platformInputContext.clear();
 +    {
 +        QInputMethodEvent inputMethodEvent;
 +        inputMethodEvent.setCommitString("y");
 +        QGuiApplication::sendEvent(edit, &inputMethodEvent);
 +    }
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // changing cursor position
 +    platformInputContext.clear();
 +    edit->setCursorPosition(0);
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // continuing with selection
 +    platformInputContext.clear();
 +    edit->moveCursorSelection(1);
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // read only disabled input method
 +    platformInputContext.clear();
 +    edit->setReadOnly(true);
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +    edit->setReadOnly(false);
 +
 +    // no updates while no focus
 +    edit->setFocus(false);
 +    platformInputContext.clear();
 +    edit->setText("Foo");
 +    QCOMPARE(platformInputContext.m_updateCallCount, 0);
 +    edit->setCursorPosition(1);
 +    QCOMPARE(platformInputContext.m_updateCallCount, 0);
 +    edit->selectAll();
 +    QCOMPARE(platformInputContext.m_updateCallCount, 0);
 +    edit->setReadOnly(true);
 +    QCOMPARE(platformInputContext.m_updateCallCount, 0);
 +}
 +
 +void tst_qquicktextedit::openInputPanel()
 +{
 +    PlatformInputContext platformInputContext;
 +    QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
 +    inputMethodPrivate->testContext = &platformInputContext;
 +
 +    QQuickView view(testFileUrl("openInputPanel.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +
 +    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
 +    QVERIFY(edit);
 +
 +    // check default values
 +    QVERIFY(edit->focusOnPress());
 +    QVERIFY(!edit->hasActiveFocus());
 +    qDebug() << &edit << qApp->focusObject();
 +    QVERIFY(qApp->focusObject() != edit);
 +
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +
 +    // input panel should open on focus
 +    QPoint centerPoint(view.width()/2, view.height()/2);
 +    Qt::KeyboardModifiers noModifiers = 0;
 +    QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QGuiApplication::processEvents();
 +    QVERIFY(edit->hasActiveFocus());
 +    QCOMPARE(qApp->focusObject(), edit);
 +    QCOMPARE(qApp->inputMethod()->visible(), true);
 +    QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
 +
 +    // input panel should be re-opened when pressing already focused TextEdit
 +    qApp->inputMethod()->hide();
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +    QVERIFY(edit->hasActiveFocus());
 +    QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QGuiApplication::processEvents();
 +    QCOMPARE(qApp->inputMethod()->visible(), true);
 +    QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
 +
 +    // input panel should stay visible if focus is lost to another text editor
 +    QSignalSpy inputPanelVisibilitySpy(qApp->inputMethod(), SIGNAL(visibleChanged()));
 +    QQuickTextEdit anotherEdit;
 +    anotherEdit.setParentItem(view.rootObject());
 +    anotherEdit.setFocus(true);
 +    QCOMPARE(qApp->inputMethod()->visible(), true);
 +    QCOMPARE(qApp->focusObject(), qobject_cast<QObject*>(&anotherEdit));
 +    QCOMPARE(inputPanelVisibilitySpy.count(), 0);
 +
 +    anotherEdit.setFocus(false);
 +    QVERIFY(qApp->focusObject() != &anotherEdit);
 +    QCOMPARE(view.activeFocusItem(), view.rootItem());
 +    anotherEdit.setFocus(true);
 +
 +    qApp->inputMethod()->hide();
 +
 +    // input panel should not be opened if TextEdit is read only
 +    edit->setReadOnly(true);
 +    edit->setFocus(true);
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +    QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QGuiApplication::processEvents();
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +
 +    // input panel should not be opened if focusOnPress is set to false
 +    edit->setFocusOnPress(false);
 +    edit->setFocus(false);
 +    edit->setFocus(true);
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +    QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +
 +    // input panel should open when openSoftwareInputPanel is called
 +    edit->openSoftwareInputPanel();
 +    QCOMPARE(qApp->inputMethod()->visible(), true);
 +
 +    // input panel should close when closeSoftwareInputPanel is called
 +    edit->closeSoftwareInputPanel();
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +
 +    inputMethodPrivate->testContext = 0;
 +}
 +
 +void tst_qquicktextedit::geometrySignals()
 +{
 +    QQmlComponent component(&engine, testFileUrl("geometrySignals.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o);
 +    QCOMPARE(o->property("bindingWidth").toInt(), 400);
 +    QCOMPARE(o->property("bindingHeight").toInt(), 500);
 +    delete o;
 +}
 +
 +void tst_qquicktextedit::pastingRichText_QTBUG_14003()
 +{
 +#ifndef QT_NO_CLIPBOARD
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.PlainText }";
 +    QQmlComponent component(&engine);
 +    component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QQuickTextEdit *obj = qobject_cast<QQuickTextEdit*>(component.create());
 +
 +    QTRY_VERIFY(obj != 0);
 +    QTRY_VERIFY(obj->textFormat() == QQuickTextEdit::PlainText);
 +
 +    QMimeData *mData = new QMimeData;
 +    mData->setHtml("<font color=\"red\">Hello</font>");
 +    QGuiApplication::clipboard()->setMimeData(mData);
 +
 +    obj->paste();
 +    QTRY_VERIFY(obj->text() == "");
 +    QTRY_VERIFY(obj->textFormat() == QQuickTextEdit::PlainText);
 +#endif
 +}
 +
 +void tst_qquicktextedit::implicitSize_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<QString>("wrap");
 +    QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap";
 +    QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap";
 +    QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap";
 +    QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap";
 +}
 +
 +void tst_qquicktextedit::implicitSize()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(QString, wrap);
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
 +
 +    QVERIFY(textObject->width() < textObject->implicitWidth());
 +    QVERIFY(textObject->height() == textObject->implicitHeight());
 +
 +    textObject->resetWidth();
 +    QVERIFY(textObject->width() == textObject->implicitWidth());
 +    QVERIFY(textObject->height() == textObject->implicitHeight());
 +}
 +
 +void tst_qquicktextedit::contentSize()
 +{
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { width: 75; height: 16; font.pixelSize: 10 }";
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QScopedPointer<QObject> object(textComponent.create());
 +    QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit *>(object.data());
 +
 +    QSignalSpy spy(textObject, SIGNAL(contentSizeChanged()));
 +
 +    textObject->setText("The quick red fox jumped over the lazy brown dog");
 +
 +    QVERIFY(textObject->contentWidth() > textObject->width());
 +    QVERIFY(textObject->contentHeight() < textObject->height());
 +    QCOMPARE(spy.count(), 1);
 +
 +    textObject->setWrapMode(QQuickTextEdit::WordWrap);
 +    QVERIFY(textObject->contentWidth() <= textObject->width());
 +    QVERIFY(textObject->contentHeight() > textObject->height());
 +    QCOMPARE(spy.count(), 2);
 +
 +    textObject->setText("The quickredfoxjumpedoverthe lazy brown dog");
 +
 +    QVERIFY(textObject->contentWidth() > textObject->width());
 +    QVERIFY(textObject->contentHeight() > textObject->height());
 +    QCOMPARE(spy.count(), 3);
 +}
 +
 +void tst_qquicktextedit::preeditCursorRectangle()
 +{
 +    QString preeditText = "super";
 +
 +    QQuickView view(testFileUrl("inputMethodEvent.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
 +    QVERIFY(edit);
 +
 +    QSignalSpy editSpy(edit, SIGNAL(cursorRectangleChanged()));
 +    QSignalSpy panelSpy(qGuiApp->inputMethod(), SIGNAL(cursorRectangleChanged()));
 +
 +    QRect currentRect;
 +
 +    QInputMethodQueryEvent query(Qt::ImCursorRectangle);
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
 +    QRect previousRect = query.value(Qt::ImCursorRectangle).toRect();
 +
 +    // Verify that the micro focus rect is positioned the same for position 0 as
 +    // it would be if there was no preedit text.
 +    QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>()
 +            << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, preeditText.length(), QVariant()));
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
 +    currentRect = query.value(Qt::ImCursorRectangle).toRect();
 +    QCOMPARE(currentRect, previousRect);
 +    QCOMPARE(editSpy.count(), 0);
 +    QCOMPARE(panelSpy.count(), 0);
 +
 +    // Verify that the micro focus rect moves to the left as the cursor position
 +    // is incremented.
 +    for (int i = 1; i <= 5; ++i) {
 +        QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>()
 +                << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, preeditText.length(), QVariant()));
 +        QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
 +        QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
 +        currentRect = query.value(Qt::ImCursorRectangle).toRect();
 +        QVERIFY(previousRect.left() < currentRect.left());
 +        QVERIFY(editSpy.count() > 0); editSpy.clear();
 +        QVERIFY(panelSpy.count() > 0); panelSpy.clear();
 +        previousRect = currentRect;
 +    }
 +
 +    // Verify that if there is no preedit cursor then the micro focus rect is the
 +    // same as it would be if it were positioned at the end of the preedit text.
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
 +    editSpy.clear();
 +    panelSpy.clear();
 +    {   QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
 +        QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent); }
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
 +    currentRect = query.value(Qt::ImCursorRectangle).toRect();
 +    QCOMPARE(currentRect, previousRect);
 +    QVERIFY(editSpy.count() > 0);
 +    QVERIFY(panelSpy.count() > 0);
 +}
 +
 +void tst_qquicktextedit::inputMethodComposing()
 +{
 +    QString text = "supercalifragisiticexpialidocious!";
 +
 +    QQuickView view(testFileUrl("inputContext.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
 +    QVERIFY(edit);
 +    QSignalSpy spy(edit, SIGNAL(inputMethodComposingChanged()));
 +    edit->setCursorPosition(12);
 +
 +    QCOMPARE(edit->isInputMethodComposing(), false);
 +
 +    {
 +        QInputMethodEvent event(text.mid(3), QList<QInputMethodEvent::Attribute>());
 +        QGuiApplication::sendEvent(edit, &event);
 +    }
 +
 +    QCOMPARE(edit->isInputMethodComposing(), true);
 +    QCOMPARE(spy.count(), 1);
 +
 +    {
 +        QInputMethodEvent event(text.mid(12), QList<QInputMethodEvent::Attribute>());
 +        QGuiApplication::sendEvent(edit, &event);
 +    }
 +    QCOMPARE(spy.count(), 1);
 +
 +    {
 +        QInputMethodEvent event;
 +        QGuiApplication::sendEvent(edit, &event);
 +    }
 +    QCOMPARE(edit->isInputMethodComposing(), false);
 +    QCOMPARE(spy.count(), 2);
 +}
 +
 +void tst_qquicktextedit::cursorRectangleSize()
 +{
 +    QQuickView *canvas = new QQuickView(testFileUrl("positionAt.qml"));
 +    QVERIFY(canvas->rootObject() != 0);
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(canvas->rootObject());
 +
 +    // make sure cursor rectangle is not at (0,0)
 +    textEdit->setX(10);
 +    textEdit->setY(10);
 +    textEdit->setCursorPosition(3);
 +    QVERIFY(textEdit != 0);
 +    textEdit->setFocus(true);
 +    canvas->show();
 +    canvas->requestActivateWindow();
 +    QTest::qWaitForWindowShown(canvas);
 +
 +    QInputMethodQueryEvent event(Qt::ImCursorRectangle);
 +    qApp->sendEvent(qApp->focusObject(), &event);
 +    QRectF cursorRectFromQuery = event.value(Qt::ImCursorRectangle).toRectF();
 +
-     QCOMPARE(cursorRectFromItem, cursorRectFromQuery.toRect());
++    QRectF cursorRectFromItem = textEdit->cursorRectangle();
 +    QRectF cursorRectFromPositionToRectangle = textEdit->positionToRectangle(textEdit->cursorPosition());
 +
 +    // item and input query cursor rectangles match
-     QCOMPARE(cursorRectFromItem, cursorRectFromPositionToRectangle.toRect());
++    QCOMPARE(cursorRectFromItem, cursorRectFromQuery);
 +
 +    // item cursor rectangle and positionToRectangle calculations match
++    QCOMPARE(cursorRectFromItem, cursorRectFromPositionToRectangle);
 +
 +    // item-canvas transform and input item transform match
 +    QCOMPARE(QQuickItemPrivate::get(textEdit)->itemToCanvasTransform(), qApp->inputMethod()->inputItemTransform());
 +
 +    // input panel cursorRectangle property and tranformed item cursor rectangle match
 +    QRectF sceneCursorRect = QQuickItemPrivate::get(textEdit)->itemToCanvasTransform().mapRect(cursorRectFromItem);
 +    QCOMPARE(sceneCursorRect, qApp->inputMethod()->cursorRectangle());
 +
 +    delete canvas;
 +}
 +
 +void tst_qquicktextedit::getText_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<int>("start");
 +    QTest::addColumn<int>("end");
 +    QTest::addColumn<QString>("expectedText");
 +
 +    const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
 +    const QString plainBoldText = QStringLiteral("This is some bold text");
 +
 +    QTest::newRow("all plain text")
 +            << standard.at(0)
 +            << 0 << standard.at(0).length()
 +            << standard.at(0);
 +
 +    QTest::newRow("plain text sub string")
 +            << standard.at(0)
 +            << 0 << 12
 +            << standard.at(0).mid(0, 12);
 +
 +    QTest::newRow("plain text sub string reversed")
 +            << standard.at(0)
 +            << 12 << 0
 +            << standard.at(0).mid(0, 12);
 +
 +    QTest::newRow("plain text cropped beginning")
 +            << standard.at(0)
 +            << -3 << 4
 +            << standard.at(0).mid(0, 4);
 +
 +    QTest::newRow("plain text cropped end")
 +            << standard.at(0)
 +            << 23 << standard.at(0).length() + 8
 +            << standard.at(0).mid(23);
 +
 +    QTest::newRow("plain text cropped beginning and end")
 +            << standard.at(0)
 +            << -9 << standard.at(0).length() + 4
 +            << standard.at(0);
 +
 +    QTest::newRow("all rich text")
 +            << richBoldText
 +            << 0 << plainBoldText.length()
 +            << plainBoldText;
 +
 +    QTest::newRow("rich text sub string")
 +            << richBoldText
 +            << 14 << 21
 +            << plainBoldText.mid(14, 7);
 +}
 +
 +void tst_qquicktextedit::getText()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(int, start);
 +    QFETCH(int, end);
 +    QFETCH(QString, expectedText);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.AutoText; text: \"" + text + "\" }";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    QCOMPARE(textEdit->getText(start, end), expectedText);
 +}
 +
 +void tst_qquicktextedit::getFormattedText_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat");
 +    QTest::addColumn<int>("start");
 +    QTest::addColumn<int>("end");
 +    QTest::addColumn<QString>("expectedText");
 +
 +    const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
 +    const QString plainBoldText = QStringLiteral("This is some bold text");
 +
 +    QTest::newRow("all plain text")
 +            << standard.at(0)
 +            << QQuickTextEdit::PlainText
 +            << 0 << standard.at(0).length()
 +            << standard.at(0);
 +
 +    QTest::newRow("plain text sub string")
 +            << standard.at(0)
 +            << QQuickTextEdit::PlainText
 +            << 0 << 12
 +            << standard.at(0).mid(0, 12);
 +
 +    QTest::newRow("plain text sub string reversed")
 +            << standard.at(0)
 +            << QQuickTextEdit::PlainText
 +            << 12 << 0
 +            << standard.at(0).mid(0, 12);
 +
 +    QTest::newRow("plain text cropped beginning")
 +            << standard.at(0)
 +            << QQuickTextEdit::PlainText
 +            << -3 << 4
 +            << standard.at(0).mid(0, 4);
 +
 +    QTest::newRow("plain text cropped end")
 +            << standard.at(0)
 +            << QQuickTextEdit::PlainText
 +            << 23 << standard.at(0).length() + 8
 +            << standard.at(0).mid(23);
 +
 +    QTest::newRow("plain text cropped beginning and end")
 +            << standard.at(0)
 +            << QQuickTextEdit::PlainText
 +            << -9 << standard.at(0).length() + 4
 +            << standard.at(0);
 +
 +    QTest::newRow("all rich (Auto) text")
 +            << richBoldText
 +            << QQuickTextEdit::AutoText
 +            << 0 << plainBoldText.length()
 +            << QString("This is some \\<.*\\>bold\\</.*\\> text");
 +
 +    QTest::newRow("all rich (Rich) text")
 +            << richBoldText
 +            << QQuickTextEdit::RichText
 +            << 0 << plainBoldText.length()
 +            << QString("This is some \\<.*\\>bold\\</.*\\> text");
 +
 +    QTest::newRow("all rich (Plain) text")
 +            << richBoldText
 +            << QQuickTextEdit::PlainText
 +            << 0 << richBoldText.length()
 +            << richBoldText;
 +
 +    QTest::newRow("rich (Auto) text sub string")
 +            << richBoldText
 +            << QQuickTextEdit::AutoText
 +            << 14 << 21
 +            << QString("\\<.*\\>old\\</.*\\> tex");
 +
 +    QTest::newRow("rich (Rich) text sub string")
 +            << richBoldText
 +            << QQuickTextEdit::RichText
 +            << 14 << 21
 +            << QString("\\<.*\\>old\\</.*\\> tex");
 +
 +    QTest::newRow("rich (Plain) text sub string")
 +            << richBoldText
 +            << QQuickTextEdit::PlainText
 +            << 17 << 27
 +            << richBoldText.mid(17, 10);
 +}
 +
 +void tst_qquicktextedit::getFormattedText()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(QQuickTextEdit::TextFormat, textFormat);
 +    QFETCH(int, start);
 +    QFETCH(int, end);
 +    QFETCH(QString, expectedText);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit {}";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    textEdit->setTextFormat(textFormat);
 +    textEdit->setText(text);
 +
 +    if (textFormat == QQuickTextEdit::RichText
 +            || (textFormat == QQuickTextEdit::AutoText && Qt::mightBeRichText(text))) {
 +        QVERIFY(textEdit->getFormattedText(start, end).contains(QRegExp(expectedText)));
 +    } else {
 +        QCOMPARE(textEdit->getFormattedText(start, end), expectedText);
 +    }
 +}
 +
 +void tst_qquicktextedit::insert_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat");
 +    QTest::addColumn<int>("selectionStart");
 +    QTest::addColumn<int>("selectionEnd");
 +    QTest::addColumn<int>("insertPosition");
 +    QTest::addColumn<QString>("insertText");
 +    QTest::addColumn<QString>("expectedText");
 +    QTest::addColumn<int>("expectedSelectionStart");
 +    QTest::addColumn<int>("expectedSelectionEnd");
 +    QTest::addColumn<int>("expectedCursorPosition");
 +    QTest::addColumn<bool>("selectionChanged");
 +    QTest::addColumn<bool>("cursorPositionChanged");
 +
 +    QTest::newRow("at cursor position (beginning)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0 << 0
 +            << QString("Hello")
 +            << QString("Hello") + standard.at(0)
 +            << 5 << 5 << 5
 +            << false << true;
 +
 +    QTest::newRow("at cursor position (end)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << standard.at(0).length() << standard.at(0).length() << standard.at(0).length()
 +            << QString("Hello")
 +            << standard.at(0) + QString("Hello")
 +            << standard.at(0).length() + 5 << standard.at(0).length() + 5 << standard.at(0).length() + 5
 +            << false << true;
 +
 +    QTest::newRow("at cursor position (middle)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 18 << 18 << 18
 +            << QString("Hello")
 +            << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
 +            << 23 << 23 << 23
 +            << false << true;
 +
 +    QTest::newRow("after cursor position (beginning)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0 << 18
 +            << QString("Hello")
 +            << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("before cursor position (end)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << standard.at(0).length() << standard.at(0).length() << 18
 +            << QString("Hello")
 +            << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
 +            << standard.at(0).length() + 5 << standard.at(0).length() + 5 << standard.at(0).length() + 5
 +            << false << true;
 +
 +    QTest::newRow("before cursor position (middle)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 18 << 18 << 0
 +            << QString("Hello")
 +            << QString("Hello") + standard.at(0)
 +            << 23 << 23 << 23
 +            << false << true;
 +
 +    QTest::newRow("after cursor position (middle)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 18 << 18 << standard.at(0).length()
 +            << QString("Hello")
 +            << standard.at(0) + QString("Hello")
 +            << 18 << 18 << 18
 +            << false << false;
 +
 +    QTest::newRow("before selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 14 << 19 << 0
 +            << QString("Hello")
 +            << QString("Hello") + standard.at(0)
 +            << 19 << 24 << 24
 +            << false << true;
 +
 +    QTest::newRow("before reversed selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 19 << 14 << 0
 +            << QString("Hello")
 +            << QString("Hello") + standard.at(0)
 +            << 19 << 24 << 19
 +            << false << true;
 +
 +    QTest::newRow("after selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 14 << 19 << standard.at(0).length()
 +            << QString("Hello")
 +            << standard.at(0) + QString("Hello")
 +            << 14 << 19 << 19
 +            << false << false;
 +
 +    QTest::newRow("after reversed selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 19 << 14 << standard.at(0).length()
 +            << QString("Hello")
 +            << standard.at(0) + QString("Hello")
 +            << 14 << 19 << 14
 +            << false << false;
 +
 +    QTest::newRow("into selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 14 << 19 << 18
 +            << QString("Hello")
 +            << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
 +            << 14 << 24 << 24
 +            << true << true;
 +
 +    QTest::newRow("into reversed selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 19 << 14 << 18
 +            << QString("Hello")
 +            << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
 +            << 14 << 24 << 14
 +            << true << false;
 +
 +    QTest::newRow("rich text into plain text")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0 << 0
 +            << QString("<b>Hello</b>")
 +            << QString("<b>Hello</b>") + standard.at(0)
 +            << 12 << 12 << 12
 +            << false << true;
 +
 +    QTest::newRow("rich text into rich text")
 +            << standard.at(0) << QQuickTextEdit::RichText
 +            << 0 << 0 << 0
 +            << QString("<b>Hello</b>")
 +            << QString("Hello") + standard.at(0)
 +            << 5 << 5 << 5
 +            << false << true;
 +
 +    QTest::newRow("rich text into auto text")
 +            << standard.at(0) << QQuickTextEdit::AutoText
 +            << 0 << 0 << 0
 +            << QString("<b>Hello</b>")
 +            << QString("Hello") + standard.at(0)
 +            << 5 << 5 << 5
 +            << false << true;
 +
 +    QTest::newRow("before start")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0 << -3
 +            << QString("Hello")
 +            << standard.at(0)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("past end")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0 << standard.at(0).length() + 3
 +            << QString("Hello")
 +            << standard.at(0)
 +            << 0 << 0 << 0
 +            << false << false;
 +}
 +
 +void tst_qquicktextedit::insert()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(QQuickTextEdit::TextFormat, textFormat);
 +    QFETCH(int, selectionStart);
 +    QFETCH(int, selectionEnd);
 +    QFETCH(int, insertPosition);
 +    QFETCH(QString, insertText);
 +    QFETCH(QString, expectedText);
 +    QFETCH(int, expectedSelectionStart);
 +    QFETCH(int, expectedSelectionEnd);
 +    QFETCH(int, expectedCursorPosition);
 +    QFETCH(bool, selectionChanged);
 +    QFETCH(bool, cursorPositionChanged);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\" }";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    textEdit->setTextFormat(textFormat);
 +    textEdit->select(selectionStart, selectionEnd);
 +
 +    QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged()));
 +    QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged()));
 +    QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged()));
 +    QSignalSpy textSpy(textEdit, SIGNAL(textChanged()));
 +    QSignalSpy cursorPositionSpy(textEdit, SIGNAL(cursorPositionChanged()));
 +
 +    textEdit->insert(insertPosition, insertText);
 +
 +    if (textFormat == QQuickTextEdit::RichText || (textFormat == QQuickTextEdit::AutoText && (
 +            Qt::mightBeRichText(text) || Qt::mightBeRichText(insertText)))) {
 +        QCOMPARE(textEdit->getText(0, expectedText.length()), expectedText);
 +    } else {
 +        QCOMPARE(textEdit->text(), expectedText);
 +
 +    }
 +    QCOMPARE(textEdit->length(), expectedText.length());
 +
 +    QCOMPARE(textEdit->selectionStart(), expectedSelectionStart);
 +    QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd);
 +    QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition);
 +
 +    if (selectionStart > selectionEnd)
 +        qSwap(selectionStart, selectionEnd);
 +
 +    QEXPECT_FAIL("into selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
 +    QEXPECT_FAIL("into reversed selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
 +    QCOMPARE(selectionSpy.count() > 0, selectionChanged);
 +    QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
 +    QEXPECT_FAIL("into reversed selection", "selectionEndChanged signal not emitted", Continue);
 +    QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
 +    QCOMPARE(textSpy.count() > 0, text != expectedText);
 +    QCOMPARE(cursorPositionSpy.count() > 0, cursorPositionChanged);
 +}
 +
 +void tst_qquicktextedit::remove_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<QQuickTextEdit::TextFormat>("textFormat");
 +    QTest::addColumn<int>("selectionStart");
 +    QTest::addColumn<int>("selectionEnd");
 +    QTest::addColumn<int>("removeStart");
 +    QTest::addColumn<int>("removeEnd");
 +    QTest::addColumn<QString>("expectedText");
 +    QTest::addColumn<int>("expectedSelectionStart");
 +    QTest::addColumn<int>("expectedSelectionEnd");
 +    QTest::addColumn<int>("expectedCursorPosition");
 +    QTest::addColumn<bool>("selectionChanged");
 +    QTest::addColumn<bool>("cursorPositionChanged");
 +
 +    const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
 +    const QString plainBoldText = QStringLiteral("This is some bold text");
 +
 +    QTest::newRow("from cursor position (beginning)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0
 +            << 0 << 5
 +            << standard.at(0).mid(5)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("to cursor position (beginning)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0
 +            << 5 << 0
 +            << standard.at(0).mid(5)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("to cursor position (end)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << standard.at(0).length() << standard.at(0).length()
 +            << standard.at(0).length() << standard.at(0).length() - 5
 +            << standard.at(0).mid(0, standard.at(0).length() - 5)
 +            << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
 +            << false << true;
 +
 +    QTest::newRow("to cursor position (end)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << standard.at(0).length() << standard.at(0).length()
 +            << standard.at(0).length() - 5 << standard.at(0).length()
 +            << standard.at(0).mid(0, standard.at(0).length() - 5)
 +            << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
 +            << false << true;
 +
 +    QTest::newRow("from cursor position (middle)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 18 << 18
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 18 << 18 << 18
 +            << false << false;
 +
 +    QTest::newRow("to cursor position (middle)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 23 << 23
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 18 << 18 << 18
 +            << false << true;
 +
 +    QTest::newRow("after cursor position (beginning)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("before cursor position (end)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << standard.at(0).length() << standard.at(0).length()
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
 +            << false << true;
 +
 +    QTest::newRow("before cursor position (middle)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 23 << 23
 +            << 0 << 5
 +            << standard.at(0).mid(5)
 +            << 18 << 18 << 18
 +            << false << true;
 +
 +    QTest::newRow("after cursor position (middle)")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 18 << 18
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 18 << 18 << 18
 +            << false << false;
 +
 +    QTest::newRow("before selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 14 << 19
 +            << 0 << 5
 +            << standard.at(0).mid(5)
 +            << 9 << 14 << 14
 +            << false << true;
 +
 +    QTest::newRow("before reversed selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 19 << 14
 +            << 0 << 5
 +            << standard.at(0).mid(5)
 +            << 9 << 14 << 9
 +            << false << true;
 +
 +    QTest::newRow("after selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 14 << 19
 +            << standard.at(0).length() - 5 << standard.at(0).length()
 +            << standard.at(0).mid(0, standard.at(0).length() - 5)
 +            << 14 << 19 << 19
 +            << false << false;
 +
 +    QTest::newRow("after reversed selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 19 << 14
 +            << standard.at(0).length() - 5 << standard.at(0).length()
 +            << standard.at(0).mid(0, standard.at(0).length() - 5)
 +            << 14 << 19 << 14
 +            << false << false;
 +
 +    QTest::newRow("from selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 14 << 24
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 14 << 19 << 19
 +            << true << true;
 +
 +    QTest::newRow("from reversed selection")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 24 << 14
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 14 << 19 << 14
 +            << true << false;
 +
 +    QTest::newRow("plain text cropped beginning")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0
 +            << -3 << 4
 +            << standard.at(0).mid(4)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("plain text cropped end")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0
 +            << 23 << standard.at(0).length() + 8
 +            << standard.at(0).mid(0, 23)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("plain text cropped beginning and end")
 +            << standard.at(0) << QQuickTextEdit::PlainText
 +            << 0 << 0
 +            << -9 << standard.at(0).length() + 4
 +            << QString()
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("all rich text")
 +            << richBoldText << QQuickTextEdit::RichText
 +            << 0 << 0
 +            << 0 << plainBoldText.length()
 +            << QString()
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("rick text sub string")
 +            << richBoldText << QQuickTextEdit::RichText
 +            << 0 << 0
 +            << 14 << 21
 +            << plainBoldText.mid(0, 14) + plainBoldText.mid(21)
 +            << 0 << 0 << 0
 +            << false << false;
 +}
 +
 +void tst_qquicktextedit::remove()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(QQuickTextEdit::TextFormat, textFormat);
 +    QFETCH(int, selectionStart);
 +    QFETCH(int, selectionEnd);
 +    QFETCH(int, removeStart);
 +    QFETCH(int, removeEnd);
 +    QFETCH(QString, expectedText);
 +    QFETCH(int, expectedSelectionStart);
 +    QFETCH(int, expectedSelectionEnd);
 +    QFETCH(int, expectedCursorPosition);
 +    QFETCH(bool, selectionChanged);
 +    QFETCH(bool, cursorPositionChanged);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\" }";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    textEdit->setTextFormat(textFormat);
 +    textEdit->select(selectionStart, selectionEnd);
 +
 +    QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged()));
 +    QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged()));
 +    QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged()));
 +    QSignalSpy textSpy(textEdit, SIGNAL(textChanged()));
 +    QSignalSpy cursorPositionSpy(textEdit, SIGNAL(cursorPositionChanged()));
 +
 +    textEdit->remove(removeStart, removeEnd);
 +
 +    if (textFormat == QQuickTextEdit::RichText
 +            || (textFormat == QQuickTextEdit::AutoText && Qt::mightBeRichText(text))) {
 +        QCOMPARE(textEdit->getText(0, expectedText.length()), expectedText);
 +    } else {
 +        QCOMPARE(textEdit->text(), expectedText);
 +    }
 +    QCOMPARE(textEdit->length(), expectedText.length());
 +
 +    if (selectionStart > selectionEnd)  //
 +        qSwap(selectionStart, selectionEnd);
 +
 +    QCOMPARE(textEdit->selectionStart(), expectedSelectionStart);
 +    QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd);
 +    QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition);
 +
 +    QEXPECT_FAIL("from selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
 +    QEXPECT_FAIL("from reversed selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
 +    QCOMPARE(selectionSpy.count() > 0, selectionChanged);
 +    QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
 +    QEXPECT_FAIL("from reversed selection", "selectionEndChanged signal not emitted", Continue);
 +    QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
 +    QCOMPARE(textSpy.count() > 0, text != expectedText);
 +
 +
 +    if (cursorPositionChanged)  //
 +        QVERIFY(cursorPositionSpy.count() > 0);
 +}
 +
 +
 +void tst_qquicktextedit::keySequence_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<QKeySequence>("sequence");
 +    QTest::addColumn<int>("selectionStart");
 +    QTest::addColumn<int>("selectionEnd");
 +    QTest::addColumn<int>("cursorPosition");
 +    QTest::addColumn<QString>("expectedText");
 +    QTest::addColumn<QString>("selectedText");
 +
 +    // standard[0] == "the [4]quick [10]brown [16]fox [20]jumped [27]over [32]the [36]lazy [41]dog"
 +
 +    QTest::newRow("select all")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectAll) << 0 << 0
 +            << 44 << standard.at(0) << standard.at(0);
 +    QTest::newRow("select end of line")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5
 +            << 44 << standard.at(0) << standard.at(0).mid(5);
 +    QTest::newRow("select end of document")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3
 +            << 44 << standard.at(0) << standard.at(0).mid(3);
 +    QTest::newRow("select end of block")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18
 +            << 44 << standard.at(0) << standard.at(0).mid(18);
 +    QTest::newRow("delete end of line")
 +            << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24
 +            << 24 << standard.at(0).mid(0, 24) << QString();
 +    QTest::newRow("move to start of line")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31
 +            << 0 << standard.at(0) << QString();
 +    QTest::newRow("move to start of block")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25
 +            << 0 << standard.at(0) << QString();
 +    QTest::newRow("move to next char")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToNextChar) << 12 << 12
 +            << 13 << standard.at(0) << QString();
 +    QTest::newRow("move to previous char")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
 +            << 2 << standard.at(0) << QString();
 +    QTest::newRow("select next char")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
 +            << 24 << standard.at(0) << standard.at(0).mid(23, 1);
 +    QTest::newRow("select previous char")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
 +            << 18 << standard.at(0) << standard.at(0).mid(18, 1);
 +    QTest::newRow("move to next word")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
 +            << 10 << standard.at(0) << QString();
 +    QTest::newRow("move to previous word")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
 +            << 4 << standard.at(0) << QString();
 +    QTest::newRow("select previous word")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11
 +            << 10 << standard.at(0) << standard.at(0).mid(10, 1);
 +    QTest::newRow("delete (selection)")
 +            << standard.at(0) << QKeySequence(QKeySequence::Delete) << 12 << 15
 +            << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString();
 +    QTest::newRow("delete (no selection)")
 +            << standard.at(0) << QKeySequence(QKeySequence::Delete) << 15 << 15
 +            << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString();
 +    QTest::newRow("delete end of word")
 +            << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfWord) << 24 << 24
 +            << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString();
 +    QTest::newRow("delete start of word")
 +            << standard.at(0) << QKeySequence(QKeySequence::DeleteStartOfWord) << 7 << 7
 +            << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString();
 +}
 +
 +void tst_qquicktextedit::keySequence()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(QKeySequence, sequence);
 +    QFETCH(int, selectionStart);
 +    QFETCH(int, selectionEnd);
 +    QFETCH(int, cursorPosition);
 +    QFETCH(QString, expectedText);
 +    QFETCH(QString, selectedText);
 +
 +    if (sequence.isEmpty()) {
 +        QSKIP("Key sequence is undefined");
 +    }
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true; text: \"" + text + "\" }";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    QQuickCanvas canvas;
 +    textEdit->setParentItem(canvas.rootItem());
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
 +
 +    textEdit->select(selectionStart, selectionEnd);
 +
 +    simulateKeys(&canvas, sequence);
 +
 +    QCOMPARE(textEdit->cursorPosition(), cursorPosition);
 +    QCOMPARE(textEdit->text(), expectedText);
 +    QCOMPARE(textEdit->selectedText(), selectedText);
 +}
 +
 +#define NORMAL 0
 +#define REPLACE_UNTIL_END 1
 +
 +void tst_qquicktextedit::undo_data()
 +{
 +    QTest::addColumn<QStringList>("insertString");
 +    QTest::addColumn<IntList>("insertIndex");
 +    QTest::addColumn<IntList>("insertMode");
 +    QTest::addColumn<QStringList>("expectedString");
 +    QTest::addColumn<bool>("use_keys");
 +
 +    for (int i=0; i<2; i++) {
 +        QString keys_str = "keyboard";
 +        bool use_keys = true;
 +        if (i==0) {
 +            keys_str = "insert";
 +            use_keys = false;
 +        }
 +
 +        {
 +            IntList insertIndex;
 +            IntList insertMode;
 +            QStringList insertString;
 +            QStringList expectedString;
 +
 +            insertIndex << -1;
 +            insertMode << NORMAL;
 +            insertString << "1";
 +
 +            insertIndex << -1;
 +            insertMode << NORMAL;
 +            insertString << "5";
 +
 +            insertIndex << 1;
 +            insertMode << NORMAL;
 +            insertString << "3";
 +
 +            insertIndex << 1;
 +            insertMode << NORMAL;
 +            insertString << "2";
 +
 +            insertIndex << 3;
 +            insertMode << NORMAL;
 +            insertString << "4";
 +
 +            expectedString << "12345";
 +            expectedString << "1235";
 +            expectedString << "135";
 +            expectedString << "15";
 +            expectedString << "";
 +
 +            QTest::newRow(QString(keys_str + "_numbers").toLatin1()) <<
 +                insertString <<
 +                insertIndex <<
 +                insertMode <<
 +                expectedString <<
 +                bool(use_keys);
 +        }
 +        {
 +            IntList insertIndex;
 +            IntList insertMode;
 +            QStringList insertString;
 +            QStringList expectedString;
 +
 +            insertIndex << -1;
 +            insertMode << NORMAL;
 +            insertString << "World"; // World
 +
 +            insertIndex << 0;
 +            insertMode << NORMAL;
 +            insertString << "Hello"; // HelloWorld
 +
 +            insertIndex << 0;
 +            insertMode << NORMAL;
 +            insertString << "Well"; // WellHelloWorld
 +
 +            insertIndex << 9;
 +            insertMode << NORMAL;
 +            insertString << "There"; // WellHelloThereWorld;
 +
 +            expectedString << "WellHelloThereWorld";
 +            expectedString << "WellHelloWorld";
 +            expectedString << "HelloWorld";
 +            expectedString << "World";
 +            expectedString << "";
 +
 +            QTest::newRow(QString(keys_str + "_helloworld").toLatin1()) <<
 +                insertString <<
 +                insertIndex <<
 +                insertMode <<
 +                expectedString <<
 +                bool(use_keys);
 +        }
 +        {
 +            IntList insertIndex;
 +            IntList insertMode;
 +            QStringList insertString;
 +            QStringList expectedString;
 +
 +            insertIndex << -1;
 +            insertMode << NORMAL;
 +            insertString << "Ensuring";
 +
 +            insertIndex << -1;
 +            insertMode << NORMAL;
 +            insertString << " instan";
 +
 +            insertIndex << 9;
 +            insertMode << NORMAL;
 +            insertString << "an ";
 +
 +            insertIndex << 10;
 +            insertMode << REPLACE_UNTIL_END;
 +            insertString << " unique instance.";
 +
 +            expectedString << "Ensuring a unique instance.";
 +            expectedString << "Ensuring a ";    // ### Not present in TextInput.
 +            expectedString << "Ensuring an instan";
 +            expectedString << "Ensuring instan";
 +            expectedString << "";
 +
 +            QTest::newRow(QString(keys_str + "_patterns").toLatin1()) <<
 +                insertString <<
 +                insertIndex <<
 +                insertMode <<
 +                expectedString <<
 +                bool(use_keys);
 +        }
 +    }
 +}
 +
 +void tst_qquicktextedit::undo()
 +{
 +    QFETCH(QStringList, insertString);
 +    QFETCH(IntList, insertIndex);
 +    QFETCH(IntList, insertMode);
 +    QFETCH(QStringList, expectedString);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    QQuickCanvas canvas;
 +    textEdit->setParentItem(canvas.rootItem());
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
 +
 +    QVERIFY(!textEdit->canUndo());
 +
 +    QSignalSpy spy(textEdit, SIGNAL(canUndoChanged()));
 +
 +    int i;
 +
 +// STEP 1: First build up an undo history by inserting or typing some strings...
 +    for (i = 0; i < insertString.size(); ++i) {
 +        if (insertIndex[i] > -1)
 +            textEdit->setCursorPosition(insertIndex[i]);
 +
 + // experimental stuff
 +        if (insertMode[i] == REPLACE_UNTIL_END) {
 +            textEdit->select(insertIndex[i], insertIndex[i] + 8);
 +
 +            // This is what I actually want...
 +            // QTest::keyClick(testWidget, Qt::Key_End, Qt::ShiftModifier);
 +        }
 +
 +        for (int j = 0; j < insertString.at(i).length(); j++)
 +            QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
 +    }
 +
 +    QCOMPARE(spy.count(), 1);
 +
 +// STEP 2: Next call undo several times and see if we can restore to the previous state
 +    for (i = 0; i < expectedString.size() - 1; ++i) {
 +        QCOMPARE(textEdit->text(), expectedString[i]);
 +        QVERIFY(textEdit->canUndo());
 +        textEdit->undo();
 +    }
 +
 +// STEP 3: Verify that we have undone everything
 +    QVERIFY(textEdit->text().isEmpty());
 +    QVERIFY(!textEdit->canUndo());
 +    QCOMPARE(spy.count(), 2);
 +}
 +
 +void tst_qquicktextedit::redo_data()
 +{
 +    QTest::addColumn<QStringList>("insertString");
 +    QTest::addColumn<IntList>("insertIndex");
 +    QTest::addColumn<QStringList>("expectedString");
 +
 +    {
 +        IntList insertIndex;
 +        QStringList insertString;
 +        QStringList expectedString;
 +
 +        insertIndex << -1;
 +        insertString << "World"; // World
 +        insertIndex << 0;
 +        insertString << "Hello"; // HelloWorld
 +        insertIndex << 0;
 +        insertString << "Well"; // WellHelloWorld
 +        insertIndex << 9;
 +        insertString << "There"; // WellHelloThereWorld;
 +
 +        expectedString << "World";
 +        expectedString << "HelloWorld";
 +        expectedString << "WellHelloWorld";
 +        expectedString << "WellHelloThereWorld";
 +
 +        QTest::newRow("Inserts and setting cursor") << insertString << insertIndex << expectedString;
 +    }
 +}
 +
 +void tst_qquicktextedit::redo()
 +{
 +    QFETCH(QStringList, insertString);
 +    QFETCH(IntList, insertIndex);
 +    QFETCH(QStringList, expectedString);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    QQuickCanvas canvas;
 +    textEdit->setParentItem(canvas.rootItem());
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
 +
 +    QVERIFY(!textEdit->canUndo());
 +    QVERIFY(!textEdit->canRedo());
 +
 +    QSignalSpy spy(textEdit, SIGNAL(canRedoChanged()));
 +
 +    int i;
 +    // inserts the diff strings at diff positions
 +    for (i = 0; i < insertString.size(); ++i) {
 +        if (insertIndex[i] > -1)
 +            textEdit->setCursorPosition(insertIndex[i]);
 +        for (int j = 0; j < insertString.at(i).length(); j++)
 +            QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
 +        QVERIFY(textEdit->canUndo());
 +        QVERIFY(!textEdit->canRedo());
 +    }
 +
 +    QCOMPARE(spy.count(), 0);
 +
 +    // undo everything
 +    while (!textEdit->text().isEmpty()) {
 +        QVERIFY(textEdit->canUndo());
 +        textEdit->undo();
 +        QVERIFY(textEdit->canRedo());
 +    }
 +
 +    QCOMPARE(spy.count(), 1);
 +
 +    for (i = 0; i < expectedString.size(); ++i) {
 +        QVERIFY(textEdit->canRedo());
 +        textEdit->redo();
 +        QCOMPARE(textEdit->text() , expectedString[i]);
 +        QVERIFY(textEdit->canUndo());
 +    }
 +    QVERIFY(!textEdit->canRedo());
 +    QCOMPARE(spy.count(), 2);
 +}
 +
 +void tst_qquicktextedit::undo_keypressevents_data()
 +{
 +    QTest::addColumn<KeyList>("keys");
 +    QTest::addColumn<QStringList>("expectedString");
 +
 +    {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        keys << "AFRAID"
 +                << Qt::Key_Home
 +                << "VERY"
 +                << Qt::Key_Left
 +                << Qt::Key_Left
 +                << Qt::Key_Left
 +                << Qt::Key_Left
 +                << "BE"
 +                << Qt::Key_End
 +                << "!";
 +
 +        expectedString << "BEVERYAFRAID!";
 +        expectedString << "BEVERYAFRAID";
 +        expectedString << "VERYAFRAID";
 +        expectedString << "AFRAID";
 +
 +        QTest::newRow("Inserts and moving cursor") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        // inserting '1234'
 +        keys << "1234" << Qt::Key_Home
 +                // skipping '12'
 +                << Qt::Key_Right << Qt::Key_Right
 +                // selecting '34'
 +                << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
 +                // deleting '34'
 +                << Qt::Key_Delete;
 +
 +        expectedString << "12";
 +        expectedString << "1234";
 +
 +        QTest::newRow("Inserts,moving,selection and delete") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        // inserting 'AB12'
 +        keys << "AB12"
 +                << Qt::Key_Home
 +                // selecting 'AB'
 +                << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
 +                << Qt::Key_Delete
 +                << QKeySequence::Undo
 +                // ### Text is selected in text input
 +//                << Qt::Key_Right
 +                << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
 +                << Qt::Key_Delete;
 +
 +        expectedString << "AB";
 +        expectedString << "AB12";
 +
 +        QTest::newRow("Inserts,moving,selection, delete and undo") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        // inserting 'ABCD'
 +        keys << "abcd"
 +                //move left two
 +                << Qt::Key_Left << Qt::Key_Left
 +                // inserting '1234'
 +                << "1234"
 +                // selecting '1234'
 +                << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier)
 +                // overwriting '1234' with '5'
 +                << "5"
 +                // undoing deletion of 'AB'
 +                << QKeySequence::Undo
 +                // ### Text is selected in text input
 +                << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier)
 +                // overwriting '1234' with '6'
 +                << "6";
 +
 +        expectedString << "ab6cd";
 +        // for versions previous to 3.2 we overwrite needed two undo operations
 +        expectedString << "ab1234cd";
 +        expectedString << "abcd";
 +
 +        QTest::newRow("Inserts,moving,selection and undo, removing selection") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        // inserting 'ABC'
 +        keys << "ABC"
 +                // removes 'C'
 +                << Qt::Key_Backspace;
 +
 +        expectedString << "AB";
 +        expectedString << "ABC";
 +
 +        QTest::newRow("Inserts,backspace") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        keys << "ABC"
 +                // removes 'C'
 +                << Qt::Key_Backspace
 +                // inserting 'Z'
 +                << "Z";
 +
 +        expectedString << "ABZ";
 +        expectedString << "AB";
 +        expectedString << "ABC";
 +
 +        QTest::newRow("Inserts,backspace,inserts") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        // inserting '123'
 +        keys << "123" << Qt::Key_Home
 +            // selecting '123'
 +             << (Qt::Key_End | Qt::ShiftModifier)
 +            // overwriting '123' with 'ABC'
 +             << "ABC";
 +
 +        expectedString << "ABC";
 +        // ### One operation in TextInput.
 +        expectedString << "A";
 +        expectedString << "123";
 +
 +        QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString;
 +    }
 +}
 +
 +void tst_qquicktextedit::undo_keypressevents()
 +{
 +    QFETCH(KeyList, keys);
 +    QFETCH(QStringList, expectedString);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true }";
 +    QQmlComponent textEditComponent(&engine);
 +    textEditComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
 +    QVERIFY(textEdit != 0);
 +
 +    QQuickCanvas canvas;
 +    textEdit->setParentItem(canvas.rootItem());
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
 +
 +    simulateKeys(&canvas, keys);
 +
 +    for (int i = 0; i < expectedString.size(); ++i) {
 +        QCOMPARE(textEdit->text() , expectedString[i]);
 +        textEdit->undo();
 +    }
 +    QVERIFY(textEdit->text().isEmpty());
 +}
 +
 +void tst_qquicktextedit::baseUrl()
 +{
 +    QUrl localUrl("file:///tests/text.qml");
 +    QUrl remoteUrl("http://qt.nokia.com/test.qml");
 +
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData("import QtQuick 2.0\n TextEdit {}", localUrl);
 +    QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit *>(textComponent.create());
 +
 +    QCOMPARE(textObject->baseUrl(), localUrl);
 +
 +    QSignalSpy spy(textObject, SIGNAL(baseUrlChanged()));
 +
 +    textObject->setBaseUrl(localUrl);
 +    QCOMPARE(textObject->baseUrl(), localUrl);
 +    QCOMPARE(spy.count(), 0);
 +
 +    textObject->setBaseUrl(remoteUrl);
 +    QCOMPARE(textObject->baseUrl(), remoteUrl);
 +    QCOMPARE(spy.count(), 1);
 +
 +    textObject->resetBaseUrl();
 +    QCOMPARE(textObject->baseUrl(), localUrl);
 +    QCOMPARE(spy.count(), 2);
 +}
 +
 +void tst_qquicktextedit::embeddedImages_data()
 +{
 +    QTest::addColumn<QUrl>("qmlfile");
 +    QTest::addColumn<QString>("error");
 +    QTest::newRow("local") << testFileUrl("embeddedImagesLocal.qml") << "";
 +    QTest::newRow("local-error") << testFileUrl("embeddedImagesLocalError.qml")
 +        << testFileUrl("embeddedImagesLocalError.qml").toString()+":3:1: QML TextEdit: Cannot open: " + testFileUrl("http/notexists.png").toString();
 +    QTest::newRow("local") << testFileUrl("embeddedImagesLocalRelative.qml") << "";
 +    QTest::newRow("remote") << testFileUrl("embeddedImagesRemote.qml") << "";
 +    QTest::newRow("remote-error") << testFileUrl("embeddedImagesRemoteError.qml")
 +        << testFileUrl("embeddedImagesRemoteError.qml").toString()+":3:1: QML TextEdit: Error downloading http://127.0.0.1:42332/notexists.png - server replied: Not found";
 +    QTest::newRow("remote") << testFileUrl("embeddedImagesRemoteRelative.qml") << "";
 +}
 +
 +void tst_qquicktextedit::embeddedImages()
 +{
 +    QFETCH(QUrl, qmlfile);
 +    QFETCH(QString, error);
 +
 +    TestHTTPServer server(42332);
 +    server.serveDirectory(testFile("http"));
 +
 +    if (!error.isEmpty())
 +        QTest::ignoreMessage(QtWarningMsg, error.toLatin1());
 +
 +    QQmlComponent textComponent(&engine, qmlfile);
 +    QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create());
 +
 +    QVERIFY(textObject != 0);
 +    QTRY_COMPARE(QQuickTextEditPrivate::get(textObject)->document->resourcesLoading(), 0);
 +
 +    QPixmap pm(testFile("http/exists.png"));
 +    if (error.isEmpty()) {
 +        QCOMPARE(textObject->width(), double(pm.width()));
 +        QCOMPARE(textObject->height(), double(pm.height()));
 +    } else {
 +        QVERIFY(16 != pm.width()); // check test is effective
 +        QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon
 +        QCOMPARE(textObject->height(), 16.0);
 +    }
 +
 +    delete textObject;
 +}
 +
 +void tst_qquicktextedit::emptytags_QTBUG_22058()
 +{
 +    QQuickView canvas(testFileUrl("qtbug-22058.qml"));
 +    QVERIFY(canvas.rootObject() != 0);
 +
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("inputField")));
 +    QVERIFY(input->hasActiveFocus());
 +
 +    QInputMethodEvent event("", QList<QInputMethodEvent::Attribute>());
 +    event.setCommitString("<b>Bold<");
 +    QGuiApplication::sendEvent(input, &event);
 +    QCOMPARE(input->text(), QString("<b>Bold<"));
 +    event.setCommitString(">");
 +    QGuiApplication::sendEvent(input, &event);
 +    QCOMPARE(input->text(), QString("<b>Bold<>"));
 +}
 +
 +QTEST_MAIN(tst_qquicktextedit)
 +
 +#include "tst_qquicktextedit.moc"
index 4141fea,0000000..bdd18d6
mode 100644,000000..100644
--- /dev/null
@@@ -1,4706 -1,0 +1,4703 @@@
-         QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
-         QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +#include <qtest.h>
 +#include <QtTest/QSignalSpy>
 +#include "../../shared/util.h"
 +#include <private/qinputmethod_p.h>
 +#include <QtQml/qqmlengine.h>
 +#include <QtQml/qqmlexpression.h>
 +#include <QFile>
 +#include <QtQuick/qquickview.h>
 +#include <QtGui/qguiapplication.h>
 +#include <QtGui/qstylehints.h>
 +#include <QInputMethod>
 +#include <private/qquicktextinput_p.h>
 +#include <private/qquicktextinput_p_p.h>
 +#include <QDebug>
 +#include <QDir>
 +#include <QStyle>
 +#include <QtOpenGL/QGLShaderProgram>
 +#include <math.h>
 +
 +#ifdef Q_OS_MAC
 +#include <Carbon/Carbon.h>
 +#endif
 +
 +#include "qplatformdefs.h"
 +#include "../../shared/platforminputcontext.h"
 +
 +Q_DECLARE_METATYPE(QQuickTextInput::SelectionMode)
 +DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
 +
 +QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual)
 +{
 +    // XXX This will be replaced by some clever persistent platform image store.
 +    QString persistent_dir = QQmlDataTest::instance()->dataDirectory();
 +    QString arch = "unknown-architecture"; // QTest needs to help with this.
 +
 +    QString expectfile = persistent_dir + QDir::separator() + filebasename + "-" + arch + ".png";
 +
 +    if (!QFile::exists(expectfile)) {
 +        actual.save(expectfile);
 +        qWarning() << "created" << expectfile;
 +    }
 +
 +    return expectfile;
 +}
 +
 +template <typename T> static T evaluate(QObject *scope, const QString &expression)
 +{
 +    QQmlExpression expr(qmlContext(scope), scope, expression);
 +    T result = expr.evaluate().value<T>();
 +    if (expr.hasError())
 +        qWarning() << expr.error().toString();
 +    return result;
 +}
 +
 +typedef QPair<int, QChar> Key;
 +
 +class tst_qquicktextinput : public QQmlDataTest
 +
 +{
 +    Q_OBJECT
 +public:
 +    tst_qquicktextinput();
 +
 +private slots:
 +    void cleanup();
 +    void text();
 +    void width();
 +    void font();
 +    void color();
 +    void wrap();
 +    void selection();
 +    void persistentSelection();
 +    void isRightToLeft_data();
 +    void isRightToLeft();
 +    void moveCursorSelection_data();
 +    void moveCursorSelection();
 +    void moveCursorSelectionSequence_data();
 +    void moveCursorSelectionSequence();
 +    void dragMouseSelection();
 +    void mouseSelectionMode_data();
 +    void mouseSelectionMode();
 +    void tripleClickSelectsAll();
 +
 +    void horizontalAlignment_data();
 +    void horizontalAlignment();
 +    void horizontalAlignment_RightToLeft();
 +    void verticalAlignment();
 +
 +    void boundingRect();
 +
 +    void positionAt();
 +
 +    void maxLength();
 +    void masks();
 +    void validators();
 +    void inputMethods();
 +
 +    void passwordCharacter();
 +    void cursorDelegate_data();
 +    void cursorDelegate();
 +    void cursorVisible();
 +    void cursorRectangle();
 +    void navigation();
 +    void navigation_RTL();
 +    void copyAndPaste();
 +    void copyAndPasteKeySequence();
 +    void canPasteEmpty();
 +    void canPaste();
 +    void readOnly();
 +
 +    void openInputPanel();
 +    void setHAlignClearCache();
 +    void focusOutClearSelection();
 +
 +    void echoMode();
 +#ifdef QT_GUI_PASSWORD_ECHO_DELAY
 +    void passwordEchoDelay();
 +#endif
 +    void geometrySignals();
 +    void contentSize();
 +
 +    void preeditAutoScroll();
 +    void preeditCursorRectangle();
 +    void inputContextMouseHandler();
 +    void inputMethodComposing();
 +    void inputMethodUpdate();
 +    void cursorRectangleSize();
 +
 +    void getText_data();
 +    void getText();
 +    void insert_data();
 +    void insert();
 +    void remove_data();
 +    void remove();
 +
 +    void keySequence_data();
 +    void keySequence();
 +
 +    void undo_data();
 +    void undo();
 +    void redo_data();
 +    void redo();
 +    void undo_keypressevents_data();
 +    void undo_keypressevents();
 +
 +    void QTBUG_19956();
 +    void QTBUG_19956_data();
 +    void QTBUG_19956_regexp();
 +
 +    void negativeDimensions();
 +
 +private:
 +    void simulateKey(QQuickView *, int key);
 +
 +    void simulateKeys(QWindow *window, const QList<Key> &keys);
 +    void simulateKeys(QWindow *window, const QKeySequence &sequence);
 +
 +    QQmlEngine engine;
 +    QStringList standard;
 +    QStringList colorStrings;
 +};
 +
 +typedef QList<int> IntList;
 +Q_DECLARE_METATYPE(IntList)
 +
 +typedef QList<Key> KeyList;
 +Q_DECLARE_METATYPE(KeyList)
 +
 +void tst_qquicktextinput::simulateKeys(QWindow *window, const QList<Key> &keys)
 +{
 +    for (int i = 0; i < keys.count(); ++i) {
 +        const int key = keys.at(i).first;
 +        const int modifiers = key & Qt::KeyboardModifierMask;
 +        const QString text = !keys.at(i).second.isNull() ? QString(keys.at(i).second) : QString();
 +
 +        QKeyEvent press(QEvent::KeyPress, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
 +        QKeyEvent release(QEvent::KeyRelease, Qt::Key(key), Qt::KeyboardModifiers(modifiers), text);
 +
 +        QGuiApplication::sendEvent(window, &press);
 +        QGuiApplication::sendEvent(window, &release);
 +    }
 +}
 +
 +void tst_qquicktextinput::simulateKeys(QWindow *window, const QKeySequence &sequence)
 +{
 +    for (int i = 0; i < sequence.count(); ++i) {
 +        const int key = sequence[i];
 +        const int modifiers = key & Qt::KeyboardModifierMask;
 +
 +        QTest::keyClick(window, Qt::Key(key & ~modifiers), Qt::KeyboardModifiers(modifiers));
 +    }
 +}
 +
 +QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
 +{
 +    for (int i = 0; i < sequence.count(); ++i)
 +        keys << Key(sequence[i], QChar());
 +    return keys;
 +}
 +
 +template <int N> QList<Key> &operator <<(QList<Key> &keys, const char (&characters)[N])
 +{
 +    for (int i = 0; i < N - 1; ++i) {
 +        int key = QTest::asciiToKey(characters[i]);
 +        QChar character = QLatin1Char(characters[i]);
 +        keys << Key(key, character);
 +    }
 +    return keys;
 +}
 +
 +QList<Key> &operator <<(QList<Key> &keys, Qt::Key key)
 +{
 +    keys << Key(key, QChar());
 +    return keys;
 +}
 +
 +void tst_qquicktextinput::cleanup()
 +{
 +    // ensure not even skipped tests with custom input context leave it dangling
 +    QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
 +    inputMethodPrivate->testContext = 0;
 +}
 +
 +tst_qquicktextinput::tst_qquicktextinput()
 +{
 +    standard << "the quick brown fox jumped over the lazy dog"
 +        << "It's supercalifragisiticexpialidocious!"
 +        << "Hello, world!"
 +        << "!dlrow ,olleH"
 +        << " spacey   text ";
 +
 +    colorStrings << "aliceblue"
 +                 << "antiquewhite"
 +                 << "aqua"
 +                 << "darkkhaki"
 +                 << "darkolivegreen"
 +                 << "dimgray"
 +                 << "palevioletred"
 +                 << "lightsteelblue"
 +                 << "#000000"
 +                 << "#AAAAAA"
 +                 << "#FFFFFF"
 +                 << "#2AC05F";
 +}
 +
 +void tst_qquicktextinput::text()
 +{
 +    {
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData("import QtQuick 2.0\nTextInput {  text: \"\"  }", QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->text(), QString(""));
 +        QCOMPARE(textinputObject->length(), 0);
 +
 +        delete textinputObject;
 +    }
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->text(), standard.at(i));
 +        QCOMPARE(textinputObject->length(), standard.at(i).length());
 +
 +        delete textinputObject;
 +    }
 +
 +}
 +
 +void tst_qquicktextinput::width()
 +{
 +    // uses Font metrics to find the width for standard
 +    {
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData("import QtQuick 2.0\nTextInput {  text: \"\" }", QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->width(), 0.0);
 +
 +        delete textinputObject;
 +    }
 +
 +    bool requiresUnhintedMetrics = !qmlDisableDistanceField();
 +
 +    for (int i = 0; i < standard.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +
 +        QString s = standard.at(i);
 +        s.replace(QLatin1Char('\n'), QChar::LineSeparator);
 +
 +        QTextLayout layout(s);
 +        layout.setFont(textinputObject->font());
 +        layout.setFlags(Qt::TextExpandTabs | Qt::TextShowMnemonic);
 +        if (requiresUnhintedMetrics) {
 +            QTextOption option;
 +            option.setUseDesignMetrics(true);
 +            layout.setTextOption(option);
 +        }
 +
 +        layout.beginLayout();
 +        forever {
 +            QTextLine line = layout.createLine();
 +            if (!line.isValid())
 +                break;
 +        }
 +
 +        layout.endLayout();
 +
 +        qreal metricWidth = ceil(layout.boundingRect().width());
 +
 +        QVERIFY(textinputObject != 0);
 +        int delta = abs(int(int(textinputObject->width()) - metricWidth));
 +        QVERIFY(delta <= 3.0); // As best as we can hope for cross-platform.
 +
 +        delete textinputObject;
 +    }
 +}
 +
 +void tst_qquicktextinput::font()
 +{
 +    //test size, then bold, then italic, then family
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextInput {  font.pointSize: 40; text: \"Hello World\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->font().pointSize(), 40);
 +        QCOMPARE(textinputObject->font().bold(), false);
 +        QCOMPARE(textinputObject->font().italic(), false);
 +
 +        delete textinputObject;
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextInput {  font.bold: true; text: \"Hello World\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->font().bold(), true);
 +        QCOMPARE(textinputObject->font().italic(), false);
 +
 +        delete textinputObject;
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextInput {  font.italic: true; text: \"Hello World\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->font().italic(), true);
 +        QCOMPARE(textinputObject->font().bold(), false);
 +
 +        delete textinputObject;
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextInput {  font.family: \"Helvetica\"; text: \"Hello World\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->font().family(), QString("Helvetica"));
 +        QCOMPARE(textinputObject->font().bold(), false);
 +        QCOMPARE(textinputObject->font().italic(), false);
 +
 +        delete textinputObject;
 +    }
 +
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextInput {  font.family: \"\"; text: \"Hello World\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->font().family(), QString(""));
 +
 +        delete textinputObject;
 +    }
 +}
 +
 +void tst_qquicktextinput::color()
 +{
 +    //test color
 +    for (int i = 0; i < colorStrings.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextInput {  color: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->color(), QColor(colorStrings.at(i)));
 +
 +        delete textinputObject;
 +    }
 +
 +    //test selection color
 +    for (int i = 0; i < colorStrings.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextInput {  selectionColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->selectionColor(), QColor(colorStrings.at(i)));
 +
 +        delete textinputObject;
 +    }
 +
 +    //test selected text color
 +    for (int i = 0; i < colorStrings.size(); i++)
 +    {
 +        QString componentStr = "import QtQuick 2.0\nTextInput {  selectedTextColor: \"" + colorStrings.at(i) + "\"; text: \"Hello World\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->selectedTextColor(), QColor(colorStrings.at(i)));
 +
 +        delete textinputObject;
 +    }
 +
 +    {
 +        QString colorStr = "#AA001234";
 +        QColor testColor("#001234");
 +        testColor.setAlpha(170);
 +
 +        QString componentStr = "import QtQuick 2.0\nTextInput {  color: \"" + colorStr + "\"; text: \"Hello World\" }";
 +        QQmlComponent textinputComponent(&engine);
 +        textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +        QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +
 +        QVERIFY(textinputObject != 0);
 +        QCOMPARE(textinputObject->color(), testColor);
 +
 +        delete textinputObject;
 +    }
 +}
 +
 +void tst_qquicktextinput::wrap()
 +{
 +    int textHeight = 0;
 +    // for specified width and wrap set true
 +    {
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData("import QtQuick 2.0\nTextInput { text: \"Hello\"; wrapMode: Text.WrapAnywhere; width: 300 }", QUrl::fromLocalFile(""));
 +        QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
 +        textHeight = textObject->height();
 +
 +        QVERIFY(textObject != 0);
 +        QVERIFY(textObject->wrapMode() == QQuickTextInput::WrapAnywhere);
 +        QCOMPARE(textObject->width(), 300.);
 +
 +        delete textObject;
 +    }
 +
 +    for (int i = 0; i < standard.count(); i++) {
 +        QString componentStr = "import QtQuick 2.0\nTextInput { wrapMode: Text.WrapAnywhere; width: 30; text: \"" + standard.at(i) + "\" }";
 +        QQmlComponent textComponent(&engine);
 +        textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +        QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
 +
 +        QVERIFY(textObject != 0);
 +        QCOMPARE(textObject->width(), 30.);
 +        QVERIFY(textObject->height() > textHeight);
 +
 +        int oldHeight = textObject->height();
 +        textObject->setWidth(100);
 +        QVERIFY(textObject->height() < oldHeight);
 +
 +        delete textObject;
 +    }
 +}
 +
 +void tst_qquicktextinput::selection()
 +{
 +    QString testStr = standard[0];
 +    QString componentStr = "import QtQuick 2.0\nTextInput {  text: \""+ testStr +"\"; }";
 +    QQmlComponent textinputComponent(&engine);
 +    textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +    QVERIFY(textinputObject != 0);
 +
 +
 +    //Test selection follows cursor
 +    for (int i=0; i<= testStr.size(); i++) {
 +        textinputObject->setCursorPosition(i);
 +        QCOMPARE(textinputObject->cursorPosition(), i);
 +        QCOMPARE(textinputObject->selectionStart(), i);
 +        QCOMPARE(textinputObject->selectionEnd(), i);
 +        QVERIFY(textinputObject->selectedText().isNull());
 +    }
 +
 +    textinputObject->setCursorPosition(0);
 +    QVERIFY(textinputObject->cursorPosition() == 0);
 +    QVERIFY(textinputObject->selectionStart() == 0);
 +    QVERIFY(textinputObject->selectionEnd() == 0);
 +    QVERIFY(textinputObject->selectedText().isNull());
 +
 +    // Verify invalid positions are ignored.
 +    textinputObject->setCursorPosition(-1);
 +    QVERIFY(textinputObject->cursorPosition() == 0);
 +    QVERIFY(textinputObject->selectionStart() == 0);
 +    QVERIFY(textinputObject->selectionEnd() == 0);
 +    QVERIFY(textinputObject->selectedText().isNull());
 +
 +    textinputObject->setCursorPosition(textinputObject->text().count()+1);
 +    QVERIFY(textinputObject->cursorPosition() == 0);
 +    QVERIFY(textinputObject->selectionStart() == 0);
 +    QVERIFY(textinputObject->selectionEnd() == 0);
 +    QVERIFY(textinputObject->selectedText().isNull());
 +
 +    //Test selection
 +    for (int i=0; i<= testStr.size(); i++) {
 +        textinputObject->select(0,i);
 +        QCOMPARE(testStr.mid(0,i), textinputObject->selectedText());
 +    }
 +    for (int i=0; i<= testStr.size(); i++) {
 +        textinputObject->select(i,testStr.size());
 +        QCOMPARE(testStr.mid(i,testStr.size()-i), textinputObject->selectedText());
 +    }
 +
 +    textinputObject->setCursorPosition(0);
 +    QVERIFY(textinputObject->cursorPosition() == 0);
 +    QVERIFY(textinputObject->selectionStart() == 0);
 +    QVERIFY(textinputObject->selectionEnd() == 0);
 +    QVERIFY(textinputObject->selectedText().isNull());
 +
 +    //Test Error Ignoring behaviour
 +    textinputObject->setCursorPosition(0);
 +    QVERIFY(textinputObject->selectedText().isNull());
 +    textinputObject->select(-10,0);
 +    QVERIFY(textinputObject->selectedText().isNull());
 +    textinputObject->select(100,110);
 +    QVERIFY(textinputObject->selectedText().isNull());
 +    textinputObject->select(0,-10);
 +    QVERIFY(textinputObject->selectedText().isNull());
 +    textinputObject->select(0,100);
 +    QVERIFY(textinputObject->selectedText().isNull());
 +    textinputObject->select(0,10);
 +    QVERIFY(textinputObject->selectedText().size() == 10);
 +    textinputObject->select(-10,10);
 +    QVERIFY(textinputObject->selectedText().size() == 10);
 +    textinputObject->select(100,101);
 +    QVERIFY(textinputObject->selectedText().size() == 10);
 +    textinputObject->select(0,-10);
 +    QVERIFY(textinputObject->selectedText().size() == 10);
 +    textinputObject->select(0,100);
 +    QVERIFY(textinputObject->selectedText().size() == 10);
 +
 +    textinputObject->deselect();
 +    QVERIFY(textinputObject->selectedText().isNull());
 +    textinputObject->select(0,10);
 +    QVERIFY(textinputObject->selectedText().size() == 10);
 +    textinputObject->deselect();
 +    QVERIFY(textinputObject->selectedText().isNull());
 +
 +    // test input method selection
 +    QSignalSpy selectionSpy(textinputObject, SIGNAL(selectedTextChanged()));
 +    textinputObject->setFocus(true);
 +    {
 +        QList<QInputMethodEvent::Attribute> attributes;
 +        attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 12, 5, QVariant());
 +        QInputMethodEvent event("", attributes);
 +        QGuiApplication::sendEvent(textinputObject, &event);
 +    }
 +    QCOMPARE(selectionSpy.count(), 1);
 +    QCOMPARE(textinputObject->selectionStart(), 12);
 +    QCOMPARE(textinputObject->selectionEnd(), 17);
 +
 +    delete textinputObject;
 +}
 +
 +void tst_qquicktextinput::persistentSelection()
 +{
 +    QQuickView canvas(testFileUrl("persistentSelection.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +    canvas.requestActivateWindow();
 +
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(canvas.rootObject());
 +    QVERIFY(input);
 +    QVERIFY(input->hasActiveFocus());
 +
 +    QSignalSpy spy(input, SIGNAL(persistentSelectionChanged()));
 +
 +    QCOMPARE(input->persistentSelection(), false);
 +
 +    input->setPersistentSelection(false);
 +    QCOMPARE(input->persistentSelection(), false);
 +    QCOMPARE(spy.count(), 0);
 +
 +    input->select(1, 4);
 +    QCOMPARE(input->property("selected").toString(), QLatin1String("ell"));
 +
 +    input->setFocus(false);
 +    QCOMPARE(input->property("selected").toString(), QString());
 +
 +    input->setFocus(true);
 +    QCOMPARE(input->property("selected").toString(), QString());
 +
 +    input->setPersistentSelection(true);
 +    QCOMPARE(input->persistentSelection(), true);
 +    QCOMPARE(spy.count(), 1);
 +
 +    input->select(1, 4);
 +    QCOMPARE(input->property("selected").toString(), QLatin1String("ell"));
 +
 +    input->setFocus(false);
 +    QCOMPARE(input->property("selected").toString(), QLatin1String("ell"));
 +
 +    input->setFocus(true);
 +    QCOMPARE(input->property("selected").toString(), QLatin1String("ell"));
 +}
 +
 +void tst_qquicktextinput::isRightToLeft_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<bool>("emptyString");
 +    QTest::addColumn<bool>("firstCharacter");
 +    QTest::addColumn<bool>("lastCharacter");
 +    QTest::addColumn<bool>("middleCharacter");
 +    QTest::addColumn<bool>("startString");
 +    QTest::addColumn<bool>("midString");
 +    QTest::addColumn<bool>("endString");
 +
 +    const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
 +    QTest::newRow("Empty") << "" << false << false << false << false << false << false << false;
 +    QTest::newRow("Neutral") << "23244242" << false << false << false << false << false << false << false;
 +    QTest::newRow("LTR") << "Hello world" << false << false << false << false << false << false << false;
 +    QTest::newRow("RTL") << QString::fromUtf16(arabic_str, 11) << false << true << true << true << true << true << true;
 +    QTest::newRow("Bidi RTL + LTR + RTL") << QString::fromUtf16(arabic_str, 11) + QString("Hello world") + QString::fromUtf16(arabic_str, 11) << false << true << true << false << true << true << true;
 +    QTest::newRow("Bidi LTR + RTL + LTR") << QString("Hello world") + QString::fromUtf16(arabic_str, 11) + QString("Hello world") << false << false << false << true << false << false << false;
 +}
 +
 +void tst_qquicktextinput::isRightToLeft()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(bool, emptyString);
 +    QFETCH(bool, firstCharacter);
 +    QFETCH(bool, lastCharacter);
 +    QFETCH(bool, middleCharacter);
 +    QFETCH(bool, startString);
 +    QFETCH(bool, midString);
 +    QFETCH(bool, endString);
 +
 +    QQuickTextInput textInput;
 +    textInput.setText(text);
 +
 +    // first test that the right string is delivered to the QString::isRightToLeft()
 +    QCOMPARE(textInput.isRightToLeft(0,0), text.mid(0,0).isRightToLeft());
 +    QCOMPARE(textInput.isRightToLeft(0,1), text.mid(0,1).isRightToLeft());
 +    QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), text.mid(text.count()-2, text.count()-1).isRightToLeft());
 +    QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), text.mid(text.count()/2, text.count()/2 + 1).isRightToLeft());
 +    QCOMPARE(textInput.isRightToLeft(0,text.count()/4), text.mid(0,text.count()/4).isRightToLeft());
 +    QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), text.mid(text.count()/4,3*text.count()/4).isRightToLeft());
 +    if (text.isEmpty())
 +        QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
 +    QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), text.mid(3*text.count()/4,text.count()-1).isRightToLeft());
 +
 +    // then test that the feature actually works
 +    QCOMPARE(textInput.isRightToLeft(0,0), emptyString);
 +    QCOMPARE(textInput.isRightToLeft(0,1), firstCharacter);
 +    QCOMPARE(textInput.isRightToLeft(text.count()-2, text.count()-1), lastCharacter);
 +    QCOMPARE(textInput.isRightToLeft(text.count()/2, text.count()/2 + 1), middleCharacter);
 +    QCOMPARE(textInput.isRightToLeft(0,text.count()/4), startString);
 +    QCOMPARE(textInput.isRightToLeft(text.count()/4,3*text.count()/4), midString);
 +    if (text.isEmpty())
 +        QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML TextInput: isRightToLeft(start, end) called with the end property being smaller than the start.");
 +    QCOMPARE(textInput.isRightToLeft(3*text.count()/4,text.count()-1), endString);
 +}
 +
 +void tst_qquicktextinput::moveCursorSelection_data()
 +{
 +    QTest::addColumn<QString>("testStr");
 +    QTest::addColumn<int>("cursorPosition");
 +    QTest::addColumn<int>("movePosition");
 +    QTest::addColumn<QQuickTextInput::SelectionMode>("mode");
 +    QTest::addColumn<int>("selectionStart");
 +    QTest::addColumn<int>("selectionEnd");
 +    QTest::addColumn<bool>("reversible");
 +
 +    // () contains the text selected by the cursor.
 +    // <> contains the actual selection.
 +
 +    QTest::newRow("(t)he|characters")
 +            << standard[0] << 0 << 1 << QQuickTextInput::SelectCharacters << 0 << 1 << true;
 +    QTest::newRow("do(g)|characters")
 +            << standard[0] << 43 << 44 << QQuickTextInput::SelectCharacters << 43 << 44 << true;
 +    QTest::newRow("jum(p)ed|characters")
 +            << standard[0] << 23 << 24 << QQuickTextInput::SelectCharacters << 23 << 24 << true;
 +    QTest::newRow("jumped( )over|characters")
 +            << standard[0] << 26 << 27 << QQuickTextInput::SelectCharacters << 26 << 27 << true;
 +    QTest::newRow("(the )|characters")
 +            << standard[0] << 0 << 4 << QQuickTextInput::SelectCharacters << 0 << 4 << true;
 +    QTest::newRow("( dog)|characters")
 +            << standard[0] << 40 << 44 << QQuickTextInput::SelectCharacters << 40 << 44 << true;
 +    QTest::newRow("( jumped )|characters")
 +            << standard[0] << 19 << 27 << QQuickTextInput::SelectCharacters << 19 << 27 << true;
 +    QTest::newRow("th(e qu)ick|characters")
 +            << standard[0] << 2 << 6 << QQuickTextInput::SelectCharacters << 2 << 6 << true;
 +    QTest::newRow("la(zy d)og|characters")
 +            << standard[0] << 38 << 42 << QQuickTextInput::SelectCharacters << 38 << 42 << true;
 +    QTest::newRow("jum(ped ov)er|characters")
 +            << standard[0] << 23 << 29 << QQuickTextInput::SelectCharacters << 23 << 29 << true;
 +    QTest::newRow("()the|characters")
 +            << standard[0] << 0 << 0 << QQuickTextInput::SelectCharacters << 0 << 0 << true;
 +    QTest::newRow("dog()|characters")
 +            << standard[0] << 44 << 44 << QQuickTextInput::SelectCharacters << 44 << 44 << true;
 +    QTest::newRow("jum()ped|characters")
 +            << standard[0] << 23 << 23 << QQuickTextInput::SelectCharacters << 23 << 23 << true;
 +
 +    QTest::newRow("<(t)he>|words")
 +            << standard[0] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 3 << true;
 +    QTest::newRow("<do(g)>|words")
 +            << standard[0] << 43 << 44 << QQuickTextInput::SelectWords << 41 << 44 << true;
 +    QTest::newRow("<jum(p)ed>|words")
 +            << standard[0] << 23 << 24 << QQuickTextInput::SelectWords << 20 << 26 << true;
 +    QTest::newRow("<jumped( )>over|words,ltr")
 +            << standard[0] << 26 << 27 << QQuickTextInput::SelectWords << 20 << 27 << false;
 +    QTest::newRow("jumped<( )over>|words,rtl")
 +            << standard[0] << 27 << 26 << QQuickTextInput::SelectWords << 26 << 31 << false;
 +    QTest::newRow("<(the )>quick|words,ltr")
 +            << standard[0] << 0 << 4 << QQuickTextInput::SelectWords << 0 << 4 << false;
 +    QTest::newRow("<(the )quick>|words,rtl")
 +            << standard[0] << 4 << 0 << QQuickTextInput::SelectWords << 0 << 9 << false;
 +    QTest::newRow("<lazy( dog)>|words,ltr")
 +            << standard[0] << 40 << 44 << QQuickTextInput::SelectWords << 36 << 44 << false;
 +    QTest::newRow("lazy<( dog)>|words,rtl")
 +            << standard[0] << 44 << 40 << QQuickTextInput::SelectWords << 40 << 44 << false;
 +    QTest::newRow("<fox( jumped )>over|words,ltr")
 +            << standard[0] << 19 << 27 << QQuickTextInput::SelectWords << 16 << 27 << false;
 +    QTest::newRow("fox<( jumped )over>|words,rtl")
 +            << standard[0] << 27 << 19 << QQuickTextInput::SelectWords << 19 << 31 << false;
 +    QTest::newRow("<th(e qu)ick>|words")
 +            << standard[0] << 2 << 6 << QQuickTextInput::SelectWords << 0 << 9 << true;
 +    QTest::newRow("<la(zy d)og|words>")
 +            << standard[0] << 38 << 42 << QQuickTextInput::SelectWords << 36 << 44 << true;
 +    QTest::newRow("<jum(ped ov)er>|words")
 +            << standard[0] << 23 << 29 << QQuickTextInput::SelectWords << 20 << 31 << true;
 +    QTest::newRow("<()>the|words")
 +            << standard[0] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << true;
 +    QTest::newRow("dog<()>|words")
 +            << standard[0] << 44 << 44 << QQuickTextInput::SelectWords << 44 << 44 << true;
 +    QTest::newRow("jum<()>ped|words")
 +            << standard[0] << 23 << 23 << QQuickTextInput::SelectWords << 23 << 23 << true;
 +
 +    QTest::newRow("Hello<(,)> |words")
 +            << standard[2] << 5 << 6 << QQuickTextInput::SelectWords << 5 << 6 << true;
 +    QTest::newRow("Hello<(, )>world|words,ltr")
 +            << standard[2] << 5 << 7 << QQuickTextInput::SelectWords << 5 << 7 << false;
 +    QTest::newRow("Hello<(, )world>|words,rtl")
 +            << standard[2] << 7 << 5 << QQuickTextInput::SelectWords << 5 << 12 << false;
 +    QTest::newRow("<Hel(lo, )>world|words,ltr")
 +            << standard[2] << 3 << 7 << QQuickTextInput::SelectWords << 0 << 7 << false;
 +    QTest::newRow("<Hel(lo, )world>|words,rtl")
 +            << standard[2] << 7 << 3 << QQuickTextInput::SelectWords << 0 << 12 << false;
 +    QTest::newRow("<Hel(lo)>,|words")
 +            << standard[2] << 3 << 5 << QQuickTextInput::SelectWords << 0 << 5 << true;
 +    QTest::newRow("Hello<()>,|words")
 +            << standard[2] << 5 << 5 << QQuickTextInput::SelectWords << 5 << 5 << true;
 +    QTest::newRow("Hello,<()>|words")
 +            << standard[2] << 6 << 6 << QQuickTextInput::SelectWords << 6 << 6 << true;
 +    QTest::newRow("Hello<,( )>world|words,ltr")
 +            << standard[2] << 6 << 7 << QQuickTextInput::SelectWords << 5 << 7 << false;
 +    QTest::newRow("Hello,<( )world>|words,rtl")
 +            << standard[2] << 7 << 6 << QQuickTextInput::SelectWords << 6 << 12 << false;
 +    QTest::newRow("Hello<,( world)>|words,ltr")
 +            << standard[2] << 6 << 12 << QQuickTextInput::SelectWords << 5 << 12 << false;
 +    QTest::newRow("Hello,<( world)>|words,rtl")
 +            << standard[2] << 12 << 6 << QQuickTextInput::SelectWords << 6 << 12 << false;
 +    QTest::newRow("Hello<,( world!)>|words,ltr")
 +            << standard[2] << 6 << 13 << QQuickTextInput::SelectWords << 5 << 13 << false;
 +    QTest::newRow("Hello,<( world!)>|words,rtl")
 +            << standard[2] << 13 << 6 << QQuickTextInput::SelectWords << 6 << 13 << false;
 +    QTest::newRow("Hello<(, world!)>|words")
 +            << standard[2] << 5 << 13 << QQuickTextInput::SelectWords << 5 << 13 << true;
 +    // Fails due to an issue with QTextBoundaryFinder and punctuation at the end of strings.
 +    // QTBUG-11365
 +    // QTest::newRow("world<(!)>|words")
 +    //         << standard[2] << 12 << 13 << QQuickTextInput::SelectWords << 12 << 13 << true;
 +    QTest::newRow("world!<()>)|words")
 +            << standard[2] << 13 << 13 << QQuickTextInput::SelectWords << 13 << 13 << true;
 +    QTest::newRow("world<()>!)|words")
 +            << standard[2] << 12 << 12 << QQuickTextInput::SelectWords << 12 << 12 << true;
 +
 +    QTest::newRow("<(,)>olleH |words")
 +            << standard[3] << 7 << 8 << QQuickTextInput::SelectWords << 7 << 8 << true;
 +    QTest::newRow("<dlrow( ,)>olleH|words,ltr")
 +            << standard[3] << 6 << 8 << QQuickTextInput::SelectWords << 1 << 8 << false;
 +    QTest::newRow("dlrow<( ,)>olleH|words,rtl")
 +            << standard[3] << 8 << 6 << QQuickTextInput::SelectWords << 6 << 8 << false;
 +    QTest::newRow("<dlrow( ,ol)leH>|words,ltr")
 +            << standard[3] << 6 << 10 << QQuickTextInput::SelectWords << 1 << 13 << false;
 +    QTest::newRow("dlrow<( ,ol)leH>|words,rtl")
 +            << standard[3] << 10 << 6 << QQuickTextInput::SelectWords << 6 << 13 << false;
 +    QTest::newRow(",<(ol)leH>,|words")
 +            << standard[3] << 8 << 10 << QQuickTextInput::SelectWords << 8 << 13 << true;
 +    QTest::newRow(",<()>olleH|words")
 +            << standard[3] << 8 << 8 << QQuickTextInput::SelectWords << 8 << 8 << true;
 +    QTest::newRow("<()>,olleH|words")
 +            << standard[3] << 7 << 7 << QQuickTextInput::SelectWords << 7 << 7 << true;
 +    QTest::newRow("<dlrow( )>,olleH|words,ltr")
 +            << standard[3] << 6 << 7 << QQuickTextInput::SelectWords << 1 << 7 << false;
 +    QTest::newRow("dlrow<( ),>olleH|words,rtl")
 +            << standard[3] << 7 << 6 << QQuickTextInput::SelectWords << 6 << 8 << false;
 +    QTest::newRow("<(dlrow )>,olleH|words,ltr")
 +            << standard[3] << 1 << 7 << QQuickTextInput::SelectWords << 1 << 7 << false;
 +    QTest::newRow("<(dlrow ),>olleH|words,rtl")
 +            << standard[3] << 7 << 1 << QQuickTextInput::SelectWords << 1 << 8 << false;
 +    QTest::newRow("<(!dlrow )>,olleH|words,ltr")
 +            << standard[3] << 0 << 7 << QQuickTextInput::SelectWords << 0 << 7 << false;
 +    QTest::newRow("<(!dlrow ),>olleH|words,rtl")
 +            << standard[3] << 7 << 0 << QQuickTextInput::SelectWords << 0 << 8 << false;
 +    QTest::newRow("(!dlrow ,)olleH|words")
 +            << standard[3] << 0 << 8 << QQuickTextInput::SelectWords << 0 << 8 << true;
 +    QTest::newRow("<(!)>dlrow|words")
 +            << standard[3] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 1 << true;
 +    QTest::newRow("<()>!dlrow|words")
 +            << standard[3] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << true;
 +    QTest::newRow("!<()>dlrow|words")
 +            << standard[3] << 1 << 1 << QQuickTextInput::SelectWords << 1 << 1 << true;
 +
 +    QTest::newRow(" <s(pac)ey>   text |words")
 +            << standard[4] << 1 << 4 << QQuickTextInput::SelectWords << 1 << 7 << true;
 +    QTest::newRow(" spacey   <t(ex)t> |words")
 +            << standard[4] << 11 << 13 << QQuickTextInput::SelectWords << 10 << 14 << false; // Should be reversible. QTBUG-11365
 +    QTest::newRow("<( )>spacey   text |words|ltr")
 +            << standard[4] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 1 << false;
 +    QTest::newRow("<( )spacey>   text |words|rtl")
 +            << standard[4] << 1 << 0 << QQuickTextInput::SelectWords << 0 << 7 << false;
 +    QTest::newRow("spacey   <text( )>|words|ltr")
 +            << standard[4] << 14 << 15 << QQuickTextInput::SelectWords << 10 << 15 << false;
 +//    QTBUG-11365
 +//    QTest::newRow("spacey   text<( )>|words|rtl")
 +//            << standard[4] << 15 << 14 << QQuickTextInput::SelectWords << 14 << 15 << false;
 +    QTest::newRow("<()> spacey   text |words")
 +            << standard[4] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << false;
 +    QTest::newRow(" spacey   text <()>|words")
 +            << standard[4] << 15 << 15 << QQuickTextInput::SelectWords << 15 << 15 << false;
 +}
 +
 +void tst_qquicktextinput::moveCursorSelection()
 +{
 +    QFETCH(QString, testStr);
 +    QFETCH(int, cursorPosition);
 +    QFETCH(int, movePosition);
 +    QFETCH(QQuickTextInput::SelectionMode, mode);
 +    QFETCH(int, selectionStart);
 +    QFETCH(int, selectionEnd);
 +    QFETCH(bool, reversible);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput {  text: \""+ testStr +"\"; }";
 +    QQmlComponent textinputComponent(&engine);
 +    textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +    QVERIFY(textinputObject != 0);
 +
 +    textinputObject->setCursorPosition(cursorPosition);
 +    textinputObject->moveCursorSelection(movePosition, mode);
 +
 +    QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
 +    QCOMPARE(textinputObject->selectionStart(), selectionStart);
 +    QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
 +
 +    if (reversible) {
 +        textinputObject->setCursorPosition(movePosition);
 +        textinputObject->moveCursorSelection(cursorPosition, mode);
 +
 +        QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart));
 +        QCOMPARE(textinputObject->selectionStart(), selectionStart);
 +        QCOMPARE(textinputObject->selectionEnd(), selectionEnd);
 +    }
 +
 +    delete textinputObject;
 +}
 +
 +void tst_qquicktextinput::moveCursorSelectionSequence_data()
 +{
 +    QTest::addColumn<QString>("testStr");
 +    QTest::addColumn<int>("cursorPosition");
 +    QTest::addColumn<int>("movePosition1");
 +    QTest::addColumn<int>("movePosition2");
 +    QTest::addColumn<int>("selection1Start");
 +    QTest::addColumn<int>("selection1End");
 +    QTest::addColumn<int>("selection2Start");
 +    QTest::addColumn<int>("selection2End");
 +
 +    // () contains the text selected by the cursor.
 +    // <> contains the actual selection.
 +    // ^ is the revised cursor position.
 +    // {} contains the revised selection.
 +
 +    QTest::newRow("the {<quick( bro)wn> f^ox} jumped|ltr")
 +            << standard[0]
 +            << 9 << 13 << 17
 +            << 4 << 15
 +            << 4 << 19;
 +    QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl")
 +            << standard[0]
 +            << 13 << 9 << 17
 +            << 9 << 15
 +            << 10 << 19;
 +    QTest::newRow("the {<quick( bro)wn> ^}fox jumped|ltr")
 +            << standard[0]
 +            << 9 << 13 << 16
 +            << 4 << 15
 +            << 4 << 16;
 +    QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl")
 +            << standard[0]
 +            << 13 << 9 << 16
 +            << 9 << 15
 +            << 10 << 16;
 +    QTest::newRow("the {<quick( bro)wn^>} fox jumped|ltr")
 +            << standard[0]
 +            << 9 << 13 << 15
 +            << 4 << 15
 +            << 4 << 15;
 +    QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl")
 +            << standard[0]
 +            << 13 << 9 << 15
 +            << 9 << 15
 +            << 10 << 15;
 +    QTest::newRow("the {<quick() ^}bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 10
 +            << 4 << 15
 +            << 4 << 10;
 +    QTest::newRow("the quick<( {^bro)wn>} fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 10
 +            << 9 << 15
 +            << 10 << 15;
 +    QTest::newRow("the {<quick^}( bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 9
 +            << 4 << 15
 +            << 4 << 9;
 +    QTest::newRow("the quick{<(^ bro)wn>} fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 9
 +            << 9 << 15
 +            << 9 << 15;
 +    QTest::newRow("the {<qui^ck}( bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 7
 +            << 4 << 15
 +            << 4 << 9;
 +    QTest::newRow("the {<qui^ck}( bro)wn> fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 7
 +            << 9 << 15
 +            << 4 << 15;
 +    QTest::newRow("the {<^quick}( bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 4
 +            << 4 << 15
 +            << 4 << 9;
 +    QTest::newRow("the {<^quick}( bro)wn> fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 4
 +            << 9 << 15
 +            << 4 << 15;
 +    QTest::newRow("the{^ <quick}( bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 3
 +            << 4 << 15
 +            << 3 << 9;
 +    QTest::newRow("the{^ <quick}( bro)wn> fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 3
 +            << 9 << 15
 +            << 3 << 15;
 +    QTest::newRow("{t^he <quick}( bro)wn> fox|ltr")
 +            << standard[0]
 +            << 9 << 13 << 1
 +            << 4 << 15
 +            << 0 << 9;
 +    QTest::newRow("{t^he <quick}( bro)wn> fox|rtl")
 +            << standard[0]
 +            << 13 << 9 << 1
 +            << 9 << 15
 +            << 0 << 15;
 +
 +    QTest::newRow("{<He(ll)o>, w^orld}!|ltr")
 +            << standard[2]
 +            << 2 << 4 << 8
 +            << 0 << 5
 +            << 0 << 12;
 +    QTest::newRow("{<He(ll)o>, w^orld}!|rtl")
 +            << standard[2]
 +            << 4 << 2 << 8
 +            << 0 << 5
 +            << 0 << 12;
 +
 +    QTest::newRow("!{dlro^w ,<o(ll)eH>}|ltr")
 +            << standard[3]
 +            << 9 << 11 << 5
 +            << 8 << 13
 +            << 1 << 13;
 +    QTest::newRow("!{dlro^w ,<o(ll)eH>}|rtl")
 +            << standard[3]
 +            << 11 << 9 << 5
 +            << 8 << 13
 +            << 1 << 13;
 +
 +    QTest::newRow("{<(^} sp)acey>   text |ltr")
 +            << standard[4]
 +            << 0 << 3 << 0
 +            << 0 << 7
 +            << 0 << 0;
 +    QTest::newRow("{<( ^}sp)acey>   text |ltr")
 +            << standard[4]
 +            << 0 << 3 << 1
 +            << 0 << 7
 +            << 0 << 1;
 +    QTest::newRow("<( {s^p)acey>}   text |rtl")
 +            << standard[4]
 +            << 3 << 0 << 2
 +            << 0 << 7
 +            << 1 << 7;
 +    QTest::newRow("<( {^sp)acey>}   text |rtl")
 +            << standard[4]
 +            << 3 << 0 << 1
 +            << 0 << 7
 +            << 1 << 7;
 +
 +    QTest::newRow(" spacey   <te(xt {^)>}|rtl")
 +            << standard[4]
 +            << 15 << 12 << 15
 +            << 10 << 15
 +            << 15 << 15;
 +//    QTBUG-11365
 +//    QTest::newRow(" spacey   <te(xt{^ )>}|rtl")
 +//            << standard[4]
 +//            << 15 << 12 << 14
 +//            << 10 << 15
 +//            << 14 << 15;
 +    QTest::newRow(" spacey   {<te(x^t} )>|ltr")
 +            << standard[4]
 +            << 12 << 15 << 13
 +            << 10 << 15
 +            << 10 << 14;
 +//    QTBUG-11365
 +//    QTest::newRow(" spacey   {<te(xt^} )>|ltr")
 +//            << standard[4]
 +//            << 12 << 15 << 14
 +//            << 10 << 15
 +//            << 10 << 14;
 +}
 +
 +void tst_qquicktextinput::moveCursorSelectionSequence()
 +{
 +    QFETCH(QString, testStr);
 +    QFETCH(int, cursorPosition);
 +    QFETCH(int, movePosition1);
 +    QFETCH(int, movePosition2);
 +    QFETCH(int, selection1Start);
 +    QFETCH(int, selection1End);
 +    QFETCH(int, selection2Start);
 +    QFETCH(int, selection2End);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput {  text: \""+ testStr +"\"; }";
 +    QQmlComponent textinputComponent(&engine);
 +    textinputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput*>(textinputComponent.create());
 +    QVERIFY(textinputObject != 0);
 +
 +    textinputObject->setCursorPosition(cursorPosition);
 +
 +    textinputObject->moveCursorSelection(movePosition1, QQuickTextInput::SelectWords);
 +    QCOMPARE(textinputObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start));
 +    QCOMPARE(textinputObject->selectionStart(), selection1Start);
 +    QCOMPARE(textinputObject->selectionEnd(), selection1End);
 +
 +    textinputObject->moveCursorSelection(movePosition2, QQuickTextInput::SelectWords);
 +    QCOMPARE(textinputObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start));
 +    QCOMPARE(textinputObject->selectionStart(), selection2Start);
 +    QCOMPARE(textinputObject->selectionEnd(), selection2End);
 +
 +    delete textinputObject;
 +}
 +
 +void tst_qquicktextinput::dragMouseSelection()
 +{
 +    QString qmlfile = testFile("mouseselection_true.qml");
 +
 +    QQuickView canvas(QUrl::fromLocalFile(qmlfile));
 +
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +    QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
 +    QVERIFY(textInputObject != 0);
 +
 +    // press-and-drag-and-release from x1 to x2
 +    int x1 = 10;
 +    int x2 = 70;
 +    int y = textInputObject->height()/2;
 +    QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
 +    QTest::mouseMove(&canvas, QPoint(x2, y));
 +    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
 +    QTest::qWait(100);
 +    QString str1;
 +    QVERIFY((str1 = textInputObject->selectedText()).length() > 3);
 +    QVERIFY(str1.length() > 3);
 +
 +    // press and drag the current selection.
 +    x1 = 40;
 +    x2 = 100;
 +    QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
 +    QTest::mouseMove(&canvas, QPoint(x2, y));
 +    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
 +    QTest::qWait(300);
 +    QString str2 = textInputObject->selectedText();
 +    QVERIFY(str2.length() > 3);
 +
 +    QVERIFY(str1 != str2);
 +}
 +
 +void tst_qquicktextinput::mouseSelectionMode_data()
 +{
 +    QTest::addColumn<QString>("qmlfile");
 +    QTest::addColumn<bool>("selectWords");
 +
 +    // import installed
 +    QTest::newRow("SelectWords") << testFile("mouseselectionmode_words.qml") << true;
 +    QTest::newRow("SelectCharacters") << testFile("mouseselectionmode_characters.qml") << false;
 +    QTest::newRow("default") << testFile("mouseselectionmode_default.qml") << false;
 +}
 +
 +void tst_qquicktextinput::mouseSelectionMode()
 +{
 +    QFETCH(QString, qmlfile);
 +    QFETCH(bool, selectWords);
 +
 +    QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +
 +    QQuickView canvas(QUrl::fromLocalFile(qmlfile));
 +
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +    QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
 +    QVERIFY(textInputObject != 0);
 +
 +    // press-and-drag-and-release from x1 to x2
 +    int x1 = 10;
 +    int x2 = 70;
 +    int y = textInputObject->height()/2;
 +    QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
 +    QTest::mouseMove(&canvas, QPoint(x2,y)); // doesn't work
 +    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
 +    QTest::qWait(300);
 +    if (selectWords) {
 +        QTRY_COMPARE(textInputObject->selectedText(), text);
 +    } else {
 +        QTRY_VERIFY(textInputObject->selectedText().length() > 3);
 +        QVERIFY(textInputObject->selectedText() != text);
 +    }
 +}
 +
 +void tst_qquicktextinput::horizontalAlignment_data()
 +{
 +    QTest::addColumn<int>("hAlign");
 +    QTest::addColumn<QString>("expectfile");
 +
 +    QTest::newRow("L") << int(Qt::AlignLeft) << "halign_left";
 +    QTest::newRow("R") << int(Qt::AlignRight) << "halign_right";
 +    QTest::newRow("C") << int(Qt::AlignHCenter) << "halign_center";
 +}
 +
 +void tst_qquicktextinput::horizontalAlignment()
 +{
 +    QSKIP("Image comparison of text is almost guaranteed to fail during development");
 +
 +    QFETCH(int, hAlign);
 +    QFETCH(QString, expectfile);
 +
 +    QQuickView canvas(testFileUrl("horizontalAlignment.qml"));
 +
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +    QObject *ob = canvas.rootObject();
 +    QVERIFY(ob != 0);
 +    ob->setProperty("horizontalAlignment",hAlign);
 +    QImage actual = canvas.grabFrameBuffer();
 +
 +    expectfile = createExpectedFileIfNotFound(expectfile, actual);
 +
 +    QImage expect(expectfile);
 +
 +    QCOMPARE(actual,expect);
 +}
 +
 +void tst_qquicktextinput::horizontalAlignment_RightToLeft()
 +{
 +    PlatformInputContext platformInputContext;
 +    QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
 +    inputMethodPrivate->testContext = &platformInputContext;
 +
 +    QQuickView canvas(testFileUrl("horizontalAlignment_RightToLeft.qml"));
 +    QQuickTextInput *textInput = canvas.rootObject()->findChild<QQuickTextInput*>("text");
 +    QVERIFY(textInput != 0);
 +    canvas.show();
 +
 +    const QString rtlText = textInput->text();
 +
 +    QQuickTextInputPrivate *textInputPrivate = QQuickTextInputPrivate::get(textInput);
 +    QVERIFY(textInputPrivate != 0);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
 +
 +    // implicit alignment should follow the reading direction of RTL text
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
 +    QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
 +
 +    // explicitly left aligned
 +    textInput->setHAlign(QQuickTextInput::AlignLeft);
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
 +    QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
 +    QCOMPARE(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll, qreal(0));
 +
 +    // explicitly right aligned
 +    textInput->setHAlign(QQuickTextInput::AlignRight);
 +    QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
 +
 +    // explicitly center aligned
 +    textInput->setHAlign(QQuickTextInput::AlignHCenter);
 +    QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignHCenter);
 +    QVERIFY(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll > 0);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll < textInput->width());
 +
 +    // reseted alignment should go back to following the text reading direction
 +    textInput->resetHAlign();
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
 +    QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
 +
 +    // mirror the text item
 +    QQuickItemPrivate::get(textInput)->setLayoutMirror(true);
 +
 +    // mirrored implicit alignment should continue to follow the reading direction of the text
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
 +    QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
 +
 +    // explicitly right aligned behaves as left aligned
 +    textInput->setHAlign(QQuickTextInput::AlignRight);
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
 +    QCOMPARE(textInput->effectiveHAlign(), QQuickTextInput::AlignLeft);
 +    QCOMPARE(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll, qreal(0));
 +
 +    // mirrored explicitly left aligned behaves as right aligned
 +    textInput->setHAlign(QQuickTextInput::AlignLeft);
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
 +    QCOMPARE(textInput->effectiveHAlign(), QQuickTextInput::AlignRight);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
 +
 +    // disable mirroring
 +    QQuickItemPrivate::get(textInput)->setLayoutMirror(false);
 +    QCOMPARE(textInput->effectiveHAlign(), textInput->hAlign());
 +    textInput->resetHAlign();
 +
 +    // English text should be implicitly left aligned
 +    textInput->setText("Hello world!");
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
 +    QCOMPARE(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll, qreal(0));
 +
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +
 +    // If there is no commited text, the preedit text should determine the alignment.
 +    textInput->setText(QString());
 +    { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
 +    { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
 +
 +    // Clear pre-edit text.  TextInput should maybe do this itself on setText, but that may be
 +    // redundant as an actual input method may take care of it.
 +    { QInputMethodEvent ev; QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
 +
 +    // empty text with implicit alignment follows the system locale-based
 +    // keyboard input direction from QInputMethod::inputDirection()
 +    textInput->setText("");
 +    platformInputContext.setInputDirection(Qt::LeftToRight);
 +    QVERIFY(qApp->inputMethod()->inputDirection() == Qt::LeftToRight);
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignLeft);
 +    QCOMPARE(textInputPrivate->boundingRect.left() - textInputPrivate->hscroll, qreal(0));
 +
 +    QSignalSpy cursorRectangleSpy(textInput, SIGNAL(cursorRectangleChanged()));
 +    platformInputContext.setInputDirection(Qt::RightToLeft);
 +    QVERIFY(qApp->inputMethod()->inputDirection() == Qt::RightToLeft);
 +    QCOMPARE(cursorRectangleSpy.count(), 1);
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
 +
 +    // set input direction while having content
 +    platformInputContext.setInputDirection(Qt::LeftToRight);
 +    textInput->setText("a");
 +    platformInputContext.setInputDirection(Qt::RightToLeft);
 +    QTest::keyClick(&canvas, Qt::Key_Backspace);
 +    QVERIFY(textInput->text().isEmpty());
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
 +
 +    // input direction changed while not having focus
 +    platformInputContext.setInputDirection(Qt::LeftToRight);
 +    textInput->setFocus(false);
 +    platformInputContext.setInputDirection(Qt::RightToLeft);
 +    textInput->setFocus(true);
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
 +
 +    textInput->setHAlign(QQuickTextInput::AlignRight);
 +    QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll >= textInput->width() - 1);
 +    QVERIFY(textInputPrivate->boundingRect.right() - textInputPrivate->hscroll <= textInput->width() + 1);
 +}
 +
 +void tst_qquicktextinput::verticalAlignment()
 +{
 +    QQuickView canvas(testFileUrl("horizontalAlignment.qml"));
 +    QQuickTextInput *textInput = canvas.rootObject()->findChild<QQuickTextInput*>("text");
 +    QVERIFY(textInput != 0);
 +    canvas.show();
 +
 +    QQuickTextInputPrivate *textInputPrivate = QQuickTextInputPrivate::get(textInput);
 +    QVERIFY(textInputPrivate != 0);
 +
 +    QCOMPARE(textInput->vAlign(), QQuickTextInput::AlignTop);
 +    QVERIFY(textInputPrivate->boundingRect.bottom() - textInputPrivate->vscroll < canvas.height() / 2);
 +    QVERIFY(textInput->cursorRectangle().bottom() < canvas.height() / 2);
 +    QVERIFY(textInput->positionToRectangle(0).bottom() < canvas.height() / 2);
 +
 +    // bottom aligned
 +    textInput->setVAlign(QQuickTextInput::AlignBottom);
 +    QCOMPARE(textInput->vAlign(), QQuickTextInput::AlignBottom);
 +    QVERIFY(textInputPrivate->boundingRect.top() - textInputPrivate->vscroll > canvas.height() / 2);
 +    QVERIFY(textInput->cursorRectangle().top() > canvas.height() / 2);
 +    QVERIFY(textInput->positionToRectangle(0).top() > canvas.height() / 2);
 +
 +    // explicitly center aligned
 +    textInput->setVAlign(QQuickTextInput::AlignVCenter);
 +    QCOMPARE(textInput->vAlign(), QQuickTextInput::AlignVCenter);
 +    QVERIFY(textInputPrivate->boundingRect.top() - textInputPrivate->vscroll < canvas.height() / 2);
 +    QVERIFY(textInputPrivate->boundingRect.bottom() - textInputPrivate->vscroll > canvas.height() / 2);
 +    QVERIFY(textInput->cursorRectangle().top() < canvas.height() / 2);
 +    QVERIFY(textInput->cursorRectangle().bottom() > canvas.height() / 2);
 +    QVERIFY(textInput->positionToRectangle(0).top() < canvas.height() / 2);
 +    QVERIFY(textInput->positionToRectangle(0).bottom() > canvas.height() / 2);
 +}
 +
 +void tst_qquicktextinput::boundingRect()
 +{
 +    QQmlComponent component(&engine);
 +    component.setData("import QtQuick 2.0\n TextInput {}", QUrl());
 +    QScopedPointer<QObject> object(component.create());
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(object.data());
 +    QVERIFY(input);
 +
 +    QCOMPARE(input->width() + input->cursorRectangle().width(), input->boundingRect().width());
 +    QCOMPARE(input->height(), input->boundingRect().height());
 +
 +    input->setText("Hello World");
 +    QCOMPARE(input->width() + input->cursorRectangle().width(), input->boundingRect().width());
 +    QCOMPARE(input->height(), input->boundingRect().height());
 +
 +    // bounding rect shouldn't exceed the size of the item, expect for the cursor width;
 +    input->setWidth(input->width() / 2);
 +    QCOMPARE(input->width() + input->cursorRectangle().width(), input->boundingRect().width());
 +    QCOMPARE(input->height(), input->boundingRect().height());
 +
 +    input->setHeight(input->height() * 2);
 +    QCOMPARE(input->width() + input->cursorRectangle().width(), input->boundingRect().width());
 +    QCOMPARE(input->height(), input->boundingRect().height());
 +
 +    QQmlComponent cursorComponent(&engine);
 +    cursorComponent.setData("import QtQuick 2.0\nRectangle { height: 20; width: 8 }", QUrl());
 +
 +    input->setCursorDelegate(&cursorComponent);
 +
 +    // If a cursor delegate is used it's size should determine the excess width.
 +    QCOMPARE(input->width() + 8, input->boundingRect().width());
 +    QCOMPARE(input->height(), input->boundingRect().height());
 +}
 +
 +void tst_qquicktextinput::positionAt()
 +{
 +    QQuickView canvas(testFileUrl("positionAt.qml"));
 +    QVERIFY(canvas.rootObject() != 0);
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +
 +    QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
 +    QVERIFY(textinputObject != 0);
 +
 +    // Check autoscrolled...
 +
 +    int pos = evaluate<int>(textinputObject, QString("positionAt(%1)").arg(textinputObject->width()/2));
 +
 +    QTextLayout layout(textinputObject->text());
 +    layout.setFont(textinputObject->font());
 +
 +    if (!qmlDisableDistanceField()) {
 +        QTextOption option;
 +        option.setUseDesignMetrics(true);
 +        layout.setTextOption(option);
 +    }
 +    layout.beginLayout();
 +    QTextLine line = layout.createLine();
 +    layout.endLayout();
 +
 +    int textLeftWidthBegin = floor(line.cursorToX(pos - 1));
 +    int textLeftWidthEnd = ceil(line.cursorToX(pos + 1));
 +    int textWidth = floor(line.horizontalAdvance());
 +
 +    QVERIFY(textLeftWidthBegin <= textWidth - textinputObject->width() / 2);
 +    QVERIFY(textLeftWidthEnd >= textWidth - textinputObject->width() / 2);
 +
 +    int x = textinputObject->positionToRectangle(pos + 1).x() - 1;
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, 0, TextInput.CursorBetweenCharacters)").arg(x)), pos + 1);
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, 0, TextInput.CursorOnCharacter)").arg(x)), pos);
 +
 +    // Check without autoscroll...
 +    textinputObject->setAutoScroll(false);
 +    pos = evaluate<int>(textinputObject, QString("positionAt(%1)").arg(textinputObject->width() / 2));
 +
 +    textLeftWidthBegin = floor(line.cursorToX(pos - 1));
 +    textLeftWidthEnd = ceil(line.cursorToX(pos + 1));
 +
 +    QVERIFY(textLeftWidthBegin <= textinputObject->width() / 2);
 +    QVERIFY(textLeftWidthEnd >= textinputObject->width() / 2);
 +
 +    x = textinputObject->positionToRectangle(pos + 1).x() - 1;
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, 0, TextInput.CursorBetweenCharacters)").arg(x)), pos + 1);
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, 0, TextInput.CursorOnCharacter)").arg(x)), pos);
 +
 +    const qreal x0 = textinputObject->positionToRectangle(pos).x();
 +    const qreal x1 = textinputObject->positionToRectangle(pos + 1).x();
 +
 +    QString preeditText = textinputObject->text().mid(0, pos);
 +    textinputObject->setText(textinputObject->text().mid(pos));
 +    textinputObject->setCursorPosition(0);
 +
 +    {   QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
 +        QVERIFY(qGuiApp->focusObject());
 +        QGuiApplication::sendEvent(qGuiApp->focusObject(), &inputEvent); }
 +
 +    // Check all points within the preedit text return the same position.
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1)").arg(0)), 0);
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1)").arg(x0 / 2)), 0);
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1)").arg(x0)), 0);
 +
 +    // Verify positioning returns to normal after the preedit text.
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1)").arg(x1)), 1);
 +    QCOMPARE(textinputObject->positionToRectangle(1).x(), x1);
 +
 +    {   QInputMethodEvent inputEvent;
 +        QVERIFY(qGuiApp->focusObject());
 +        QGuiApplication::sendEvent(qGuiApp->focusObject(), &inputEvent); }
 +
 +    // With wrapping.
 +    textinputObject->setWrapMode(QQuickTextInput::WrapAnywhere);
 +
 +    const qreal y0 = line.height() / 2;
 +    const qreal y1 = line.height() * 3 / 2;
 +
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, %2)").arg(x0).arg(y0)), pos);
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, %2)").arg(x1).arg(y0)), pos + 1);
 +
 +    int newLinePos = evaluate<int>(textinputObject, QString("positionAt(%1, %2)").arg(x0).arg(y1));
 +    QVERIFY(newLinePos > pos);
 +    QCOMPARE(evaluate<int>(textinputObject, QString("positionAt(%1, %2)").arg(x1).arg(y1)), newLinePos + 1);
 +}
 +
 +void tst_qquicktextinput::maxLength()
 +{
 +    QQuickView canvas(testFileUrl("maxLength.qml"));
 +    QVERIFY(canvas.rootObject() != 0);
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +
 +    QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
 +    QVERIFY(textinputObject != 0);
 +    QVERIFY(textinputObject->text().isEmpty());
 +    QVERIFY(textinputObject->maxLength() == 10);
 +    foreach (const QString &str, standard) {
 +        QVERIFY(textinputObject->text().length() <= 10);
 +        textinputObject->setText(str);
 +        QVERIFY(textinputObject->text().length() <= 10);
 +    }
 +
 +    textinputObject->setText("");
 +    QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
 +    for (int i=0; i<20; i++) {
 +        QTRY_COMPARE(textinputObject->text().length(), qMin(i,10));
 +        //simulateKey(&canvas, Qt::Key_A);
 +        QTest::keyPress(&canvas, Qt::Key_A);
 +        QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
 +        QTest::qWait(50);
 +    }
 +}
 +
 +void tst_qquicktextinput::masks()
 +{
 +    //Not a comprehensive test of the possible masks, that's done elsewhere (QLineEdit)
 +    //QString componentStr = "import QtQuick 2.0\nTextInput {  inputMask: 'HHHHhhhh'; }";
 +    QQuickView canvas(testFileUrl("masks.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QVERIFY(canvas.rootObject() != 0);
 +    QQuickTextInput *textinputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject());
 +    QVERIFY(textinputObject != 0);
 +    QTRY_VERIFY(textinputObject->hasActiveFocus() == true);
 +    QVERIFY(textinputObject->text().length() == 0);
 +    QCOMPARE(textinputObject->inputMask(), QString("HHHHhhhh; "));
 +    QCOMPARE(textinputObject->length(), 8);
 +    for (int i=0; i<10; i++) {
 +        QTRY_COMPARE(qMin(i,8), textinputObject->text().length());
 +        QCOMPARE(textinputObject->length(), 8);
 +        QCOMPARE(textinputObject->getText(0, qMin(i, 8)), QString(qMin(i, 8), 'a'));
 +        QCOMPARE(textinputObject->getText(qMin(i, 8), 8), QString(8 - qMin(i, 8), ' '));
 +        QCOMPARE(i>=4, textinputObject->hasAcceptableInput());
 +        //simulateKey(&canvas, Qt::Key_A);
 +        QTest::keyPress(&canvas, Qt::Key_A);
 +        QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
 +        QTest::qWait(50);
 +    }
 +}
 +
 +void tst_qquicktextinput::validators()
 +{
 +    // Note that this test assumes that the validators are working properly
 +    // so you may need to run their tests first. All validators are checked
 +    // here to ensure that their exposure to QML is working.
 +
 +    QLocale::setDefault(QLocale(QStringLiteral("C")));
 +
 +    QQuickView canvas(testFileUrl("validators.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +
 +    QLocale defaultLocale;
 +    QLocale enLocale("en");
 +    QLocale deLocale("de_DE");
 +
 +    QQuickTextInput *intInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("intInput")));
 +    QVERIFY(intInput);
 +    QSignalSpy intSpy(intInput, SIGNAL(acceptableInputChanged()));
 +
 +    QQuickIntValidator *intValidator = qobject_cast<QQuickIntValidator *>(intInput->validator());
 +    QVERIFY(intValidator);
 +    QCOMPARE(intValidator->localeName(), defaultLocale.name());
 +    QCOMPARE(intInput->validator()->locale(), defaultLocale);
 +    intValidator->setLocaleName(enLocale.name());
 +    QCOMPARE(intValidator->localeName(), enLocale.name());
 +    QCOMPARE(intInput->validator()->locale(), enLocale);
 +    intValidator->resetLocaleName();
 +    QCOMPARE(intValidator->localeName(), defaultLocale.name());
 +    QCOMPARE(intInput->validator()->locale(), defaultLocale);
 +
 +    intInput->setFocus(true);
 +    QTRY_VERIFY(intInput->hasActiveFocus());
 +    QCOMPARE(intInput->hasAcceptableInput(), false);
 +    QCOMPARE(intInput->property("acceptable").toBool(), false);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(intInput->text(), QLatin1String("1"));
 +    QCOMPARE(intInput->hasAcceptableInput(), false);
 +    QCOMPARE(intInput->property("acceptable").toBool(), false);
 +    QCOMPARE(intSpy.count(), 0);
 +    QTest::keyPress(&canvas, Qt::Key_2);
 +    QTest::keyRelease(&canvas, Qt::Key_2, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(intInput->text(), QLatin1String("1"));
 +    QCOMPARE(intInput->hasAcceptableInput(), false);
 +    QCOMPARE(intInput->property("acceptable").toBool(), false);
 +    QCOMPARE(intSpy.count(), 0);
 +    QTest::keyPress(&canvas, Qt::Key_Period);
 +    QTest::keyRelease(&canvas, Qt::Key_Period, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(intInput->text(), QLatin1String("1"));
 +    QCOMPARE(intInput->hasAcceptableInput(), false);
 +    QTest::keyPress(&canvas, Qt::Key_Comma);
 +    QTest::keyRelease(&canvas, Qt::Key_Comma, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(intInput->text(), QLatin1String("1,"));
 +    QCOMPARE(intInput->hasAcceptableInput(), false);
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QTest::keyRelease(&canvas, Qt::Key_Backspace, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(intInput->text(), QLatin1String("1"));
 +    QCOMPARE(intInput->hasAcceptableInput(), false);
 +    intValidator->setLocaleName(deLocale.name());
 +    QTest::keyPress(&canvas, Qt::Key_Period);
 +    QTest::keyRelease(&canvas, Qt::Key_Period, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(intInput->text(), QLatin1String("1."));
 +    QCOMPARE(intInput->hasAcceptableInput(), false);
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QTest::keyRelease(&canvas, Qt::Key_Backspace, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(intInput->text(), QLatin1String("1"));
 +    QCOMPARE(intInput->hasAcceptableInput(), false);
 +    intValidator->resetLocaleName();
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QCOMPARE(intInput->text(), QLatin1String("11"));
 +    QCOMPARE(intInput->hasAcceptableInput(), true);
 +    QCOMPARE(intInput->property("acceptable").toBool(), true);
 +    QCOMPARE(intSpy.count(), 1);
 +    QTest::keyPress(&canvas, Qt::Key_0);
 +    QTest::keyRelease(&canvas, Qt::Key_0, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QCOMPARE(intInput->text(), QLatin1String("11"));
 +    QCOMPARE(intInput->hasAcceptableInput(), true);
 +    QCOMPARE(intInput->property("acceptable").toBool(), true);
 +    QCOMPARE(intSpy.count(), 1);
 +
 +    QQuickTextInput *dblInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("dblInput")));
 +    QVERIFY(dblInput);
 +    QSignalSpy dblSpy(dblInput, SIGNAL(acceptableInputChanged()));
 +
 +    QQuickDoubleValidator *dblValidator = qobject_cast<QQuickDoubleValidator *>(dblInput->validator());
 +    QVERIFY(dblValidator);
 +    QCOMPARE(dblValidator->localeName(), defaultLocale.name());
 +    QCOMPARE(dblInput->validator()->locale(), defaultLocale);
 +    dblValidator->setLocaleName(enLocale.name());
 +    QCOMPARE(dblValidator->localeName(), enLocale.name());
 +    QCOMPARE(dblInput->validator()->locale(), enLocale);
 +    dblValidator->resetLocaleName();
 +    QCOMPARE(dblValidator->localeName(), defaultLocale.name());
 +    QCOMPARE(dblInput->validator()->locale(), defaultLocale);
 +
 +    dblInput->setFocus(true);
 +    QVERIFY(dblInput->hasActiveFocus() == true);
 +    QCOMPARE(dblInput->hasAcceptableInput(), false);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), false);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("1"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), false);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), false);
 +    QCOMPARE(dblSpy.count(), 0);
 +    QTest::keyPress(&canvas, Qt::Key_2);
 +    QTest::keyRelease(&canvas, Qt::Key_2, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), true);
 +    QCOMPARE(dblSpy.count(), 1);
 +    QTest::keyPress(&canvas, Qt::Key_Comma);
 +    QTest::keyRelease(&canvas, Qt::Key_Comma, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12,"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12,"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    dblValidator->setLocaleName(deLocale.name());
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12,1"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12,11"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QTest::keyRelease(&canvas, Qt::Key_Backspace, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12,1"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QTest::keyRelease(&canvas, Qt::Key_Backspace, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12,"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QTest::keyRelease(&canvas, Qt::Key_Backspace, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    dblValidator->resetLocaleName();
 +    QTest::keyPress(&canvas, Qt::Key_Period);
 +    QTest::keyRelease(&canvas, Qt::Key_Period, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12."));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), true);
 +    QCOMPARE(dblSpy.count(), 1);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), true);
 +    QCOMPARE(dblSpy.count(), 1);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), true);
 +    QCOMPARE(dblSpy.count(), 1);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), true);
 +    QCOMPARE(dblSpy.count(), 1);
 +
 +    // Ensure the validator doesn't prevent characters being removed.
 +    dblInput->setValidator(intInput->validator());
 +    QCOMPARE(dblInput->text(), QLatin1String("12.11"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), false);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), false);
 +    QCOMPARE(dblSpy.count(), 2);
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QTest::keyRelease(&canvas, Qt::Key_Backspace, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), false);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), false);
 +    QCOMPARE(dblSpy.count(), 2);
 +    // Once unacceptable input is in anything goes until it reaches an acceptable state again.
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12.11"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), false);
 +    QCOMPARE(dblSpy.count(), 2);
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QTest::keyRelease(&canvas, Qt::Key_Backspace, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12.1"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), false);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), false);
 +    QCOMPARE(dblSpy.count(), 2);
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QTest::keyRelease(&canvas, Qt::Key_Backspace, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12."));
 +    QCOMPARE(dblInput->hasAcceptableInput(), false);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), false);
 +    QCOMPARE(dblSpy.count(), 2);
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QTest::keyRelease(&canvas, Qt::Key_Backspace, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("12"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), false);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), false);
 +    QCOMPARE(dblSpy.count(), 2);
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QTest::keyRelease(&canvas, Qt::Key_Backspace, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(dblInput->text(), QLatin1String("1"));
 +    QCOMPARE(dblInput->hasAcceptableInput(), false);
 +    QCOMPARE(dblInput->property("acceptable").toBool(), false);
 +    QCOMPARE(dblSpy.count(), 2);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QCOMPARE(dblInput->text(), QLatin1String("11"));
 +    QCOMPARE(dblInput->property("acceptable").toBool(), true);
 +    QCOMPARE(dblInput->hasAcceptableInput(), true);
 +    QCOMPARE(dblSpy.count(), 3);
 +
 +    QQuickTextInput *strInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("strInput")));
 +    QVERIFY(strInput);
 +    QSignalSpy strSpy(strInput, SIGNAL(acceptableInputChanged()));
 +    strInput->setFocus(true);
 +    QVERIFY(strInput->hasActiveFocus() == true);
 +    QCOMPARE(strInput->hasAcceptableInput(), false);
 +    QCOMPARE(strInput->property("acceptable").toBool(), false);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(strInput->text(), QLatin1String(""));
 +    QCOMPARE(strInput->hasAcceptableInput(), false);
 +    QCOMPARE(strInput->property("acceptable").toBool(), false);
 +    QCOMPARE(strSpy.count(), 0);
 +    QTest::keyPress(&canvas, Qt::Key_A);
 +    QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(strInput->text(), QLatin1String("a"));
 +    QCOMPARE(strInput->hasAcceptableInput(), false);
 +    QCOMPARE(strInput->property("acceptable").toBool(), false);
 +    QCOMPARE(strSpy.count(), 0);
 +    QTest::keyPress(&canvas, Qt::Key_A);
 +    QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(strInput->text(), QLatin1String("aa"));
 +    QCOMPARE(strInput->hasAcceptableInput(), true);
 +    QCOMPARE(strInput->property("acceptable").toBool(), true);
 +    QCOMPARE(strSpy.count(), 1);
 +    QTest::keyPress(&canvas, Qt::Key_A);
 +    QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(strInput->text(), QLatin1String("aaa"));
 +    QCOMPARE(strInput->hasAcceptableInput(), true);
 +    QCOMPARE(strInput->property("acceptable").toBool(), true);
 +    QCOMPARE(strSpy.count(), 1);
 +    QTest::keyPress(&canvas, Qt::Key_A);
 +    QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(strInput->text(), QLatin1String("aaaa"));
 +    QCOMPARE(strInput->hasAcceptableInput(), true);
 +    QCOMPARE(strInput->property("acceptable").toBool(), true);
 +    QCOMPARE(strSpy.count(), 1);
 +    QTest::keyPress(&canvas, Qt::Key_A);
 +    QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(strInput->text(), QLatin1String("aaaa"));
 +    QCOMPARE(strInput->hasAcceptableInput(), true);
 +    QCOMPARE(strInput->property("acceptable").toBool(), true);
 +    QCOMPARE(strSpy.count(), 1);
 +
 +    QQuickTextInput *unvalidatedInput = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("unvalidatedInput")));
 +    QVERIFY(unvalidatedInput);
 +    QSignalSpy unvalidatedSpy(unvalidatedInput, SIGNAL(acceptableInputChanged()));
 +    unvalidatedInput->setFocus(true);
 +    QVERIFY(unvalidatedInput->hasActiveFocus() == true);
 +    QCOMPARE(unvalidatedInput->hasAcceptableInput(), true);
 +    QCOMPARE(unvalidatedInput->property("acceptable").toBool(), true);
 +    QTest::keyPress(&canvas, Qt::Key_1);
 +    QTest::keyRelease(&canvas, Qt::Key_1, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(unvalidatedInput->text(), QLatin1String("1"));
 +    QCOMPARE(unvalidatedInput->hasAcceptableInput(), true);
 +    QCOMPARE(unvalidatedInput->property("acceptable").toBool(), true);
 +    QCOMPARE(unvalidatedSpy.count(), 0);
 +    QTest::keyPress(&canvas, Qt::Key_A);
 +    QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
 +    QTest::qWait(50);
 +    QTRY_COMPARE(unvalidatedInput->text(), QLatin1String("1a"));
 +    QCOMPARE(unvalidatedInput->hasAcceptableInput(), true);
 +    QCOMPARE(unvalidatedInput->property("acceptable").toBool(), true);
 +    QCOMPARE(unvalidatedSpy.count(), 0);
 +}
 +
 +void tst_qquicktextinput::inputMethods()
 +{
 +    QQuickView canvas(testFileUrl("inputmethods.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +
 +    // test input method hints
 +    QVERIFY(canvas.rootObject() != 0);
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(canvas.rootObject());
 +    QVERIFY(input != 0);
 +    QVERIFY(input->inputMethodHints() & Qt::ImhNoPredictiveText);
 +    QSignalSpy inputMethodHintSpy(input, SIGNAL(inputMethodHintsChanged()));
 +    input->setInputMethodHints(Qt::ImhUppercaseOnly);
 +    QVERIFY(input->inputMethodHints() & Qt::ImhUppercaseOnly);
 +    QCOMPARE(inputMethodHintSpy.count(), 1);
 +    input->setInputMethodHints(Qt::ImhUppercaseOnly);
 +    QCOMPARE(inputMethodHintSpy.count(), 1);
 +
 +    // default value
 +    QQuickTextInput plainInput;
 +    QCOMPARE(plainInput.inputMethodHints(), Qt::ImhNone);
 +
 +    input->setFocus(true);
 +    QVERIFY(input->hasActiveFocus() == true);
 +    // test that input method event is committed
 +    QInputMethodEvent event;
 +    event.setCommitString( "My ", -12, 0);
 +    QTRY_COMPARE(qGuiApp->focusObject(), input);
 +    QGuiApplication::sendEvent(qGuiApp->focusObject(), &event);
 +    QCOMPARE(input->text(), QString("My Hello world!"));
 +
 +    input->setCursorPosition(2);
 +    event.setCommitString("Your", -2, 2);
 +    QGuiApplication::sendEvent(qGuiApp->focusObject(), &event);
 +    QCOMPARE(input->text(), QString("Your Hello world!"));
 +    QCOMPARE(input->cursorPosition(), 4);
 +
 +    input->setCursorPosition(7);
 +    event.setCommitString("Goodbye", -2, 5);
 +    QGuiApplication::sendEvent(qGuiApp->focusObject(), &event);
 +    QCOMPARE(input->text(), QString("Your Goodbye world!"));
 +    QCOMPARE(input->cursorPosition(), 12);
 +
 +    input->setCursorPosition(8);
 +    event.setCommitString("Our", -8, 4);
 +    QGuiApplication::sendEvent(qGuiApp->focusObject(), &event);
 +    QCOMPARE(input->text(), QString("Our Goodbye world!"));
 +    QCOMPARE(input->cursorPosition(), 7);
 +
 +    // test that basic tentative commit gets to text property on preedit state
 +    input->setText("");
 +    QList<QInputMethodEvent::Attribute> attributes;
 +    QInputMethodEvent preeditEvent("test", attributes);
 +    preeditEvent.setTentativeCommitString("test");
 +    QGuiApplication::sendEvent(input, &preeditEvent);
 +    QCOMPARE(input->text(), QString("test"));
 +
 +    // tentative commit not allowed present in surrounding text
 +    QInputMethodQueryEvent queryEvent(Qt::ImSurroundingText);
 +    QGuiApplication::sendEvent(input, &queryEvent);
 +    QCOMPARE(queryEvent.value(Qt::ImSurroundingText).toString(), QString(""));
 +
 +    // if text with tentative commit does not validate, not allowed to be part of text property
 +    input->setText(""); // ensure input state is reset
 +    QValidator *validator = new QIntValidator(0, 100);
 +    input->setValidator(validator);
 +    QGuiApplication::sendEvent(input, &preeditEvent);
 +    QCOMPARE(input->text(), QString(""));
 +    input->setValidator(0);
 +    delete validator;
 +
 +    // input should reset selection even if replacement parameters are out of bounds
 +    input->setText("text");
 +    input->setCursorPosition(0);
 +    input->moveCursorSelection(input->text().length());
 +    event.setCommitString("replacement", -input->text().length(), input->text().length());
 +    QGuiApplication::sendEvent(qGuiApp->focusObject(), &event);
 +    QCOMPARE(input->selectionStart(), input->selectionEnd());
 +
 +    QInputMethodQueryEvent enabledQueryEvent(Qt::ImEnabled);
 +    QGuiApplication::sendEvent(input, &enabledQueryEvent);
 +    QCOMPARE(enabledQueryEvent.value(Qt::ImEnabled).toBool(), true);
 +
 +    input->setReadOnly(true);
 +    QGuiApplication::sendEvent(input, &enabledQueryEvent);
 +    QCOMPARE(enabledQueryEvent.value(Qt::ImEnabled).toBool(), false);
 +}
 +
 +/*
 +TextInput element should only handle left/right keys until the cursor reaches
 +the extent of the text, then they should ignore the keys.
 +
 +*/
 +void tst_qquicktextinput::navigation()
 +{
 +    QQuickView canvas(testFileUrl("navigation.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
 +
 +    QVERIFY(input != 0);
 +    input->setCursorPosition(0);
 +    QTRY_VERIFY(input->hasActiveFocus() == true);
 +    simulateKey(&canvas, Qt::Key_Left);
 +    QVERIFY(input->hasActiveFocus() == false);
 +    simulateKey(&canvas, Qt::Key_Right);
 +    QVERIFY(input->hasActiveFocus() == true);
 +    //QT-2944: If text is selected, ensure we deselect upon cursor motion
 +    input->setCursorPosition(input->text().length());
 +    input->select(0,input->text().length());
 +    QVERIFY(input->selectionStart() != input->selectionEnd());
 +    simulateKey(&canvas, Qt::Key_Right);
 +    QVERIFY(input->selectionStart() == input->selectionEnd());
 +    QVERIFY(input->selectionStart() == input->text().length());
 +    QVERIFY(input->hasActiveFocus() == true);
 +    simulateKey(&canvas, Qt::Key_Right);
 +    QVERIFY(input->hasActiveFocus() == false);
 +    simulateKey(&canvas, Qt::Key_Left);
 +    QVERIFY(input->hasActiveFocus() == true);
 +
 +    // Up and Down should NOT do Home/End, even on Mac OS X (QTBUG-10438).
 +    input->setCursorPosition(2);
 +    QCOMPARE(input->cursorPosition(),2);
 +    simulateKey(&canvas, Qt::Key_Up);
 +    QCOMPARE(input->cursorPosition(),2);
 +    simulateKey(&canvas, Qt::Key_Down);
 +    QCOMPARE(input->cursorPosition(),2);
 +}
 +
 +void tst_qquicktextinput::navigation_RTL()
 +{
 +    QQuickView canvas(testFileUrl("navigation.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
 +
 +    QVERIFY(input != 0);
 +    const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
 +    input->setText(QString::fromUtf16(arabic_str, 11));
 +
 +    input->setCursorPosition(0);
 +    QTRY_VERIFY(input->hasActiveFocus() == true);
 +
 +    // move off
 +    simulateKey(&canvas, Qt::Key_Right);
 +    QVERIFY(input->hasActiveFocus() == false);
 +
 +    // move back
 +    simulateKey(&canvas, Qt::Key_Left);
 +    QVERIFY(input->hasActiveFocus() == true);
 +
 +    input->setCursorPosition(input->text().length());
 +    QVERIFY(input->hasActiveFocus() == true);
 +
 +    // move off
 +    simulateKey(&canvas, Qt::Key_Left);
 +    QVERIFY(input->hasActiveFocus() == false);
 +
 +    // move back
 +    simulateKey(&canvas, Qt::Key_Right);
 +    QVERIFY(input->hasActiveFocus() == true);
 +}
 +
 +void tst_qquicktextinput::copyAndPaste() {
 +#ifndef QT_NO_CLIPBOARD
 +
 +#ifdef Q_OS_MAC
 +    {
 +        PasteboardRef pasteboard;
 +        OSStatus status = PasteboardCreate(0, &pasteboard);
 +        if (status == noErr)
 +            CFRelease(pasteboard);
 +        else
 +            QSKIP("This machine doesn't support the clipboard");
 +    }
 +#endif
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    // copy and paste
 +    QCOMPARE(textInput->text().length(), 12);
 +    textInput->select(0, textInput->text().length());;
 +    textInput->copy();
 +    QCOMPARE(textInput->selectedText(), QString("Hello world!"));
 +    QCOMPARE(textInput->selectedText().length(), 12);
 +    textInput->setCursorPosition(0);
 +    QVERIFY(textInput->canPaste());
 +    textInput->paste();
 +    QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
 +    QCOMPARE(textInput->text().length(), 24);
 +
 +    // can paste
 +    QVERIFY(textInput->canPaste());
 +    textInput->setReadOnly(true);
 +    QVERIFY(!textInput->canPaste());
 +    textInput->setReadOnly(false);
 +    QVERIFY(textInput->canPaste());
 +
 +    // select word
 +    textInput->setCursorPosition(0);
 +    textInput->selectWord();
 +    QCOMPARE(textInput->selectedText(), QString("Hello"));
 +
 +    // select all and cut
 +    textInput->selectAll();
 +    textInput->cut();
 +    QCOMPARE(textInput->text().length(), 0);
 +    textInput->paste();
 +    QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
 +    QCOMPARE(textInput->text().length(), 24);
 +
 +    // clear copy buffer
 +    QClipboard *clipboard = QGuiApplication::clipboard();
 +    QVERIFY(clipboard);
 +    clipboard->clear();
 +    QVERIFY(!textInput->canPaste());
 +
 +    // test that copy functionality is disabled
 +    // when echo mode is set to hide text/password mode
 +    int index = 0;
 +    while (index < 4) {
 +        QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index);
 +        textInput->setEchoMode(echoMode);
 +        textInput->setText("My password");
 +        textInput->select(0, textInput->text().length());;
 +        textInput->copy();
 +        if (echoMode == QQuickTextInput::Normal) {
 +            QVERIFY(!clipboard->text().isEmpty());
 +            QCOMPARE(clipboard->text(), QString("My password"));
 +            clipboard->clear();
 +        } else {
 +            QVERIFY(clipboard->text().isEmpty());
 +        }
 +        index++;
 +    }
 +
 +    delete textInput;
 +#endif
 +}
 +
 +void tst_qquicktextinput::copyAndPasteKeySequence() {
 +#ifndef QT_NO_CLIPBOARD
 +
 +#ifdef Q_OS_MAC
 +    {
 +        PasteboardRef pasteboard;
 +        OSStatus status = PasteboardCreate(0, &pasteboard);
 +        if (status == noErr)
 +            CFRelease(pasteboard);
 +        else
 +            QSKIP("This machine doesn't support the clipboard");
 +    }
 +#endif
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\"; focus: true }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    QQuickCanvas canvas;
 +    textInput->setParentItem(canvas.rootItem());
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
 +
 +    // copy and paste
 +    QVERIFY(textInput->hasActiveFocus());
 +    QCOMPARE(textInput->text().length(), 12);
 +    textInput->select(0, textInput->text().length());
 +    simulateKeys(&canvas, QKeySequence::Copy);
 +    QCOMPARE(textInput->selectedText(), QString("Hello world!"));
 +    QCOMPARE(textInput->selectedText().length(), 12);
 +    textInput->setCursorPosition(0);
 +    QVERIFY(textInput->canPaste());
 +    simulateKeys(&canvas, QKeySequence::Paste);
 +    QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
 +    QCOMPARE(textInput->text().length(), 24);
 +
 +    // select all and cut
 +    simulateKeys(&canvas, QKeySequence::SelectAll);
 +    simulateKeys(&canvas, QKeySequence::Cut);
 +    QCOMPARE(textInput->text().length(), 0);
 +    simulateKeys(&canvas, QKeySequence::Paste);
 +    QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
 +    QCOMPARE(textInput->text().length(), 24);
 +
 +    // clear copy buffer
 +    QClipboard *clipboard = QGuiApplication::clipboard();
 +    QVERIFY(clipboard);
 +    clipboard->clear();
 +    QVERIFY(!textInput->canPaste());
 +
 +    // test that copy functionality is disabled
 +    // when echo mode is set to hide text/password mode
 +    int index = 0;
 +    while (index < 4) {
 +        QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index);
 +        textInput->setEchoMode(echoMode);
 +        textInput->setText("My password");
 +        textInput->select(0, textInput->text().length());;
 +        simulateKeys(&canvas, QKeySequence::Copy);
 +        if (echoMode == QQuickTextInput::Normal) {
 +            QVERIFY(!clipboard->text().isEmpty());
 +            QCOMPARE(clipboard->text(), QString("My password"));
 +            clipboard->clear();
 +        } else {
 +            QVERIFY(clipboard->text().isEmpty());
 +        }
 +        index++;
 +    }
 +
 +    delete textInput;
 +#endif
 +}
 +
 +void tst_qquicktextinput::canPasteEmpty() {
 +#ifndef QT_NO_CLIPBOARD
 +
 +    QGuiApplication::clipboard()->clear();
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    bool cp = !textInput->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
 +    QCOMPARE(textInput->canPaste(), cp);
 +
 +#endif
 +}
 +
 +void tst_qquicktextinput::canPaste() {
 +#ifndef QT_NO_CLIPBOARD
 +
 +    QGuiApplication::clipboard()->setText("Some text");
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    bool cp = !textInput->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
 +    QCOMPARE(textInput->canPaste(), cp);
 +
 +#endif
 +}
 +
 +void tst_qquicktextinput::passwordCharacter()
 +{
 +    QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\"; font.family: \"Helvetica\"; echoMode: TextInput.Password }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    textInput->setPasswordCharacter("X");
 +    qreal implicitWidth = textInput->implicitWidth();
 +    textInput->setPasswordCharacter(".");
 +
 +    // QTBUG-12383 content is updated and redrawn
 +    QVERIFY(textInput->implicitWidth() < implicitWidth);
 +
 +    delete textInput;
 +}
 +
 +void tst_qquicktextinput::cursorDelegate_data()
 +{
 +    QTest::addColumn<QUrl>("source");
 +    QTest::newRow("out of line") << testFileUrl("cursorTest.qml");
 +    QTest::newRow("in line") << testFileUrl("cursorTestInline.qml");
 +    QTest::newRow("external") << testFileUrl("cursorTestExternal.qml");
 +}
 +
 +void tst_qquicktextinput::cursorDelegate()
 +{
 +    QFETCH(QUrl, source);
 +    QQuickView view(source);
 +    view.show();
 +    view.requestActivateWindow();
 +    QQuickTextInput *textInputObject = view.rootObject()->findChild<QQuickTextInput*>("textInputObject");
 +    QVERIFY(textInputObject != 0);
 +    QVERIFY(textInputObject->findChild<QQuickItem*>("cursorInstance"));
 +    //Test Delegate gets created
 +    textInputObject->setFocus(true);
 +    QQuickItem* delegateObject = textInputObject->findChild<QQuickItem*>("cursorInstance");
 +    QVERIFY(delegateObject);
 +    QCOMPARE(delegateObject->property("localProperty").toString(), QString("Hello"));
 +    //Test Delegate gets moved
 +    for (int i=0; i<= textInputObject->text().length(); i++) {
 +        textInputObject->setCursorPosition(i);
-     QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x()));
-     QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y()));
++        QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
++        QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
 +    }
 +    textInputObject->setCursorPosition(0);
- static QRect round(const QRectF &r) {
-     return QRect(qRound(r.left()), qRound(r.top()), qCeil(r.width()), qCeil(r.height())); }
++    QCOMPARE(textInputObject->cursorRectangle().x(), delegateObject->x());
++    QCOMPARE(textInputObject->cursorRectangle().y(), delegateObject->y());
 +    //Test Delegate gets deleted
 +    textInputObject->setCursorDelegate(0);
 +    QVERIFY(!textInputObject->findChild<QQuickItem*>("cursorInstance"));
 +}
 +
 +void tst_qquicktextinput::cursorVisible()
 +{
 +    QQuickView view(testFileUrl("cursorVisible.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +
 +    QQuickTextInput input;
 +    input.componentComplete();
 +    QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool)));
 +
 +    QCOMPARE(input.isCursorVisible(), false);
 +
 +    input.setCursorVisible(true);
 +    QCOMPARE(input.isCursorVisible(), true);
 +    QCOMPARE(spy.count(), 1);
 +
 +    input.setCursorVisible(false);
 +    QCOMPARE(input.isCursorVisible(), false);
 +    QCOMPARE(spy.count(), 2);
 +
 +    input.setFocus(true);
 +    QCOMPARE(input.isCursorVisible(), false);
 +    QCOMPARE(spy.count(), 2);
 +
 +    input.setParentItem(view.rootObject());
 +    QCOMPARE(input.isCursorVisible(), true);
 +    QCOMPARE(spy.count(), 3);
 +
 +    input.setFocus(false);
 +    QCOMPARE(input.isCursorVisible(), false);
 +    QCOMPARE(spy.count(), 4);
 +
 +    input.setFocus(true);
 +    QCOMPARE(input.isCursorVisible(), true);
 +    QCOMPARE(spy.count(), 5);
 +
 +    QQuickView alternateView;
 +    alternateView.show();
 +    alternateView.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&alternateView);
 +
 +    QCOMPARE(input.isCursorVisible(), false);
 +    QCOMPARE(spy.count(), 6);
 +
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QCOMPARE(input.isCursorVisible(), true);
 +    QCOMPARE(spy.count(), 7);
 +}
 +
-     QRect r;
 +void tst_qquicktextinput::cursorRectangle()
 +{
 +
 +    QString text = "Hello World!";
 +
 +    QQuickTextInput input;
 +    input.setText(text);
 +    input.componentComplete();
 +
 +    QTextLayout layout(text);
 +    layout.setFont(input.font());
 +    if (!qmlDisableDistanceField()) {
 +        QTextOption option;
 +        option.setUseDesignMetrics(true);
 +        layout.setTextOption(option);
 +    }
 +    layout.beginLayout();
 +    QTextLine line = layout.createLine();
 +    layout.endLayout();
 +
 +    input.setWidth(line.cursorToX(5, QTextLine::Leading));
 +    input.setHeight(qCeil(line.height() * 3 / 2));
 +
-         QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-         QCOMPARE(round(input.positionToRectangle(i)), r);
++    QRectF r;
 +
 +    // some tolerance for different fonts.
 +#ifdef Q_OS_LINUX
 +    const int error = 2;
 +#else
 +    const int error = 5;
 +#endif
 +
 +    for (int i = 0; i <= 5; ++i) {
 +        input.setCursorPosition(i);
 +        r = input.cursorRectangle();
 +
 +        QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing)));
 +        QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading)));
-     QVERIFY(r.left() < input.width());
++        QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++        QCOMPARE(input.positionToRectangle(i), r);
 +    }
 +
 +    // Check the cursor rectangle remains within the input bounding rect when auto scrolling.
-         QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-         QCOMPARE(round(input.positionToRectangle(i)), r);
++    QVERIFY(r.left() < input.width() + error);
 +    QVERIFY(r.right() >= input.width() - error);
 +
 +    for (int i = 6; i < text.length(); ++i) {
 +        input.setCursorPosition(i);
 +        QCOMPARE(r, input.cursorRectangle());
-         QCOMPARE(r.top(), 0);
++        QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++        QCOMPARE(input.positionToRectangle(i), r);
 +    }
 +
 +    for (int i = text.length() - 2; i >= 0; --i) {
 +        input.setCursorPosition(i);
 +        r = input.cursorRectangle();
-         QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-         QCOMPARE(round(input.positionToRectangle(i)), r);
++        QCOMPARE(r.top(), 0.);
 +        QVERIFY(r.right() >= 0);
-         QCOMPARE(r.top(), 0);
-         QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-         QCOMPARE(round(input.positionToRectangle(i)), r);
++        QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++        QCOMPARE(input.positionToRectangle(i), r);
 +    }
 +
 +    // Check position with word wrap.
 +    input.setWrapMode(QQuickTextInput::WordWrap);
 +    input.setAutoScroll(false);
 +    for (int i = 0; i <= 5; ++i) {
 +        input.setCursorPosition(i);
 +        r = input.cursorRectangle();
 +
 +        QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing)));
 +        QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading)));
-     QCOMPARE(r.left(), 0);
++        QCOMPARE(r.top(), 0.);
++        QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++        QCOMPARE(input.positionToRectangle(i), r);
 +    }
 +
 +    input.setCursorPosition(6);
 +    r = input.cursorRectangle();
-     QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-     QCOMPARE(round(input.positionToRectangle(6)), r);
++    QCOMPARE(r.left(), 0.);
 +    QVERIFY(r.top() > line.height() - error);
-         QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-         QCOMPARE(round(input.positionToRectangle(i)), r);
++    QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++    QCOMPARE(input.positionToRectangle(6), r);
 +
 +    for (int i = 7; i < text.length(); ++i) {
 +        input.setCursorPosition(i);
 +        r = input.cursorRectangle();
 +        QVERIFY(r.top() > line.height() - error);
-         QCOMPARE(r.top(), 0);
-         QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-         QCOMPARE(round(round(input.positionToRectangle(i))), r);
++        QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++        QCOMPARE(input.positionToRectangle(i), r);
 +    }
 +
 +    // Check vertical scrolling with word wrap.
 +    input.setAutoScroll(true);
 +    for (int i = 0; i <= 5; ++i) {
 +        input.setCursorPosition(i);
 +        r = input.cursorRectangle();
 +
 +        QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing)));
 +        QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading)));
-     QCOMPARE(r.left(), 0);
++        QCOMPARE(r.top(), 0.);
++        QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++        QCOMPARE(input.positionToRectangle(i), r);
 +    }
 +
 +    input.setCursorPosition(6);
 +    r = input.cursorRectangle();
-     QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-     QCOMPARE(round(input.positionToRectangle(6)), r);
++    QCOMPARE(r.left(), 0.);
 +    QVERIFY(r.bottom() >= input.height() - error);
-         QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-         QCOMPARE(round(input.positionToRectangle(i)), r);
++    QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++    QCOMPARE(input.positionToRectangle(6), r);
 +
 +    for (int i = 7; i < text.length(); ++i) {
 +        input.setCursorPosition(i);
 +        r = input.cursorRectangle();
 +        QVERIFY(r.bottom() >= input.height() - error);
-         QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-         QCOMPARE(round(input.positionToRectangle(i)), r);
++        QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++        QCOMPARE(input.positionToRectangle(i), r);
 +    }
 +
 +    for (int i = text.length() - 2; i >= 6; --i) {
 +        input.setCursorPosition(i);
 +        r = input.cursorRectangle();
 +        QVERIFY(r.bottom() >= input.height() - error);
-         QCOMPARE(r.top(), 0);
-         QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRect(), r);
-         QCOMPARE(round(input.positionToRectangle(i)), r);
++        QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++        QCOMPARE(input.positionToRectangle(i), r);
 +    }
 +
 +    for (int i = 5; i >= 0; --i) {
 +        input.setCursorPosition(i);
 +        r = input.cursorRectangle();
-     QRect cursorRectFromItem = textInput->cursorRectangle();
++        QCOMPARE(r.top(), 0.);
++        QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
++        QCOMPARE(input.positionToRectangle(i), r);
 +    }
 +
 +    input.setText("Hi!");
 +    input.setHAlign(QQuickTextInput::AlignRight);
 +    r = input.cursorRectangle();
 +    QVERIFY(r.left() < input.width() + error);
 +    QVERIFY(r.right() >= input.width() - error);
 +}
 +
 +void tst_qquicktextinput::readOnly()
 +{
 +    QQuickView canvas(testFileUrl("readOnly.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
 +
 +    QVERIFY(input != 0);
 +    QTRY_VERIFY(input->hasActiveFocus() == true);
 +    QVERIFY(input->isReadOnly() == true);
 +    QString initial = input->text();
 +    for (int k=Qt::Key_0; k<=Qt::Key_Z; k++)
 +        simulateKey(&canvas, k);
 +    simulateKey(&canvas, Qt::Key_Return);
 +    simulateKey(&canvas, Qt::Key_Space);
 +    simulateKey(&canvas, Qt::Key_Escape);
 +    QCOMPARE(input->text(), initial);
 +
 +    input->setCursorPosition(3);
 +    input->setReadOnly(false);
 +    QCOMPARE(input->isReadOnly(), false);
 +    QCOMPARE(input->cursorPosition(), input->text().length());
 +}
 +
 +void tst_qquicktextinput::echoMode()
 +{
 +    QQuickView canvas(testFileUrl("echoMode.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
 +
 +    QVERIFY(input != 0);
 +    QTRY_VERIFY(input->hasActiveFocus() == true);
 +    QString initial = input->text();
 +    Qt::InputMethodHints ref;
 +    QCOMPARE(initial, QLatin1String("ABCDefgh"));
 +    QCOMPARE(input->echoMode(), QQuickTextInput::Normal);
 +    QCOMPARE(input->displayText(), input->text());
 +    //Normal
 +    ref &= ~Qt::ImhHiddenText;
 +    ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData);
 +    QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref);
 +    input->setEchoMode(QQuickTextInput::NoEcho);
 +    QCOMPARE(input->text(), initial);
 +    QCOMPARE(input->displayText(), QLatin1String(""));
 +    QCOMPARE(input->passwordCharacter(), QLatin1String("*"));
 +    //NoEcho
 +    ref |= Qt::ImhHiddenText;
 +    ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData);
 +    QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref);
 +    input->setEchoMode(QQuickTextInput::Password);
 +    //Password
 +    ref |= Qt::ImhHiddenText;
 +    ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData);
 +    QCOMPARE(input->text(), initial);
 +    QCOMPARE(input->displayText(), QLatin1String("********"));
 +    QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref);
 +    // clearing input hints do not clear bits set by echo mode
 +    input->setInputMethodHints(Qt::ImhNone);
 +    QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref);
 +    input->setPasswordCharacter(QChar('Q'));
 +    QCOMPARE(input->passwordCharacter(), QLatin1String("Q"));
 +    QCOMPARE(input->text(), initial);
 +    QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
 +    input->setEchoMode(QQuickTextInput::PasswordEchoOnEdit);
 +    //PasswordEchoOnEdit
 +    ref &= ~Qt::ImhHiddenText;
 +    ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData);
 +    QCOMPARE((Qt::InputMethodHints) input->inputMethodQuery(Qt::ImHints).toInt(), ref);
 +    QCOMPARE(input->text(), initial);
 +    QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ"));
 +    QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ"));
 +    QTest::keyPress(&canvas, Qt::Key_A);//Clearing previous entry is part of PasswordEchoOnEdit
 +    QTest::keyRelease(&canvas, Qt::Key_A, Qt::NoModifier ,10);
 +    QCOMPARE(input->text(), QLatin1String("a"));
 +    QCOMPARE(input->displayText(), QLatin1String("a"));
 +    QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("a"));
 +    input->setFocus(false);
 +    QVERIFY(input->hasActiveFocus() == false);
 +    QCOMPARE(input->displayText(), QLatin1String("Q"));
 +    QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("Q"));
 +    input->setFocus(true);
 +    QVERIFY(input->hasActiveFocus());
 +    QInputMethodEvent inputEvent;
 +    inputEvent.setCommitString(initial);
 +    QGuiApplication::sendEvent(input, &inputEvent);
 +    QCOMPARE(input->text(), initial);
 +    QCOMPARE(input->displayText(), initial);
 +    QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
 +}
 +
 +#ifdef QT_GUI_PASSWORD_ECHO_DELAY
 +void tst_qquicktextinput::passwordEchoDelay()
 +{
 +    QQuickView canvas(testFileUrl("echoMode.qml"));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
 +
 +    QVERIFY(canvas.rootObject() != 0);
 +
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
 +
 +    QChar fillChar = QLatin1Char('*');
 +
 +    input->setEchoMode(QQuickTextInput::Password);
 +    QCOMPARE(input->displayText(), QString(8, fillChar));
 +    input->setText(QString());
 +    QCOMPARE(input->displayText(), QString());
 +
 +    QTest::keyPress(&canvas, '0');
 +    QTest::keyPress(&canvas, '1');
 +    QTest::keyPress(&canvas, '2');
 +    QCOMPARE(input->displayText(), QString(2, fillChar) + QLatin1Char('2'));
 +    QTest::keyPress(&canvas, '3');
 +    QTest::keyPress(&canvas, '4');
 +    QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QCOMPARE(input->displayText(), QString(4, fillChar));
 +    QTest::keyPress(&canvas, '4');
 +    QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
 +    QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
 +    QTRY_COMPARE(input->displayText(), QString(5, fillChar));
 +    QTest::keyPress(&canvas, '5');
 +    QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
 +    input->setFocus(false);
 +    QVERIFY(!input->hasFocus());
 +    QCOMPARE(input->displayText(), QString(6, fillChar));
 +    input->setFocus(true);
 +    QTRY_VERIFY(input->hasFocus());
 +    QCOMPARE(input->displayText(), QString(6, fillChar));
 +    QTest::keyPress(&canvas, '6');
 +    QCOMPARE(input->displayText(), QString(6, fillChar) + QLatin1Char('6'));
 +
 +    QInputMethodEvent ev;
 +    ev.setCommitString(QLatin1String("7"));
 +    QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev);
 +    QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));
 +
 +    input->setCursorPosition(3);
 +    QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));
 +    QTest::keyPress(&canvas, 'a');
 +    QCOMPARE(input->displayText(), QString(3, fillChar) + QLatin1Char('a') + QString(5, fillChar));
 +    QTest::keyPress(&canvas, Qt::Key_Backspace);
 +    QCOMPARE(input->displayText(), QString(8, fillChar));
 +}
 +#endif
 +
 +
 +void tst_qquicktextinput::simulateKey(QQuickView *view, int key)
 +{
 +    QKeyEvent press(QKeyEvent::KeyPress, key, 0);
 +    QKeyEvent release(QKeyEvent::KeyRelease, key, 0);
 +
 +    QGuiApplication::sendEvent(view, &press);
 +    QGuiApplication::sendEvent(view, &release);
 +}
 +
 +
 +void tst_qquicktextinput::openInputPanel()
 +{
 +    PlatformInputContext platformInputContext;
 +    QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
 +    inputMethodPrivate->testContext = &platformInputContext;
 +
 +    QQuickView view(testFileUrl("openInputPanel.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
 +    QVERIFY(input);
 +
 +    // check default values
 +    QVERIFY(input->focusOnPress());
 +    QVERIFY(!input->hasActiveFocus());
 +    QVERIFY(qApp->focusObject() != input);
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +
 +    // input panel should open on focus
 +    QPoint centerPoint(view.width()/2, view.height()/2);
 +    Qt::KeyboardModifiers noModifiers = 0;
 +    QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QGuiApplication::processEvents();
 +    QVERIFY(input->hasActiveFocus());
 +    QCOMPARE(qApp->focusObject(), input);
 +    QCOMPARE(qApp->inputMethod()->visible(), true);
 +    QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
 +
 +    // input panel should be re-opened when pressing already focused TextInput
 +    qApp->inputMethod()->hide();
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +    QVERIFY(input->hasActiveFocus());
 +    QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QGuiApplication::processEvents();
 +    QCOMPARE(qApp->inputMethod()->visible(), true);
 +    QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
 +
 +    // input panel should stay visible if focus is lost to another text inputor
 +    QSignalSpy inputPanelVisibilitySpy(qApp->inputMethod(), SIGNAL(visibleChanged()));
 +    QQuickTextInput anotherInput;
 +    anotherInput.componentComplete();
 +    anotherInput.setParentItem(view.rootObject());
 +    anotherInput.setFocus(true);
 +    QCOMPARE(qApp->inputMethod()->visible(), true);
 +    QCOMPARE(qApp->focusObject(), qobject_cast<QObject*>(&anotherInput));
 +    QCOMPARE(inputPanelVisibilitySpy.count(), 0);
 +
 +    anotherInput.setFocus(false);
 +    QVERIFY(qApp->focusObject() != &anotherInput);
 +    QCOMPARE(view.activeFocusItem(), view.rootItem());
 +    anotherInput.setFocus(true);
 +
 +    qApp->inputMethod()->hide();
 +
 +    // input panel should not be opened if TextInput is read only
 +    input->setReadOnly(true);
 +    input->setFocus(true);
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +    QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QGuiApplication::processEvents();
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +
 +    // input panel should not be opened if focusOnPress is set to false
 +    input->setFocusOnPress(false);
 +    input->setFocus(false);
 +    input->setFocus(true);
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +    QTest::mousePress(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +
 +    // input panel should open when openSoftwareInputPanel is called
 +    input->openSoftwareInputPanel();
 +    QCOMPARE(qApp->inputMethod()->visible(), true);
 +
 +    // input panel should close when closeSoftwareInputPanel is called
 +    input->closeSoftwareInputPanel();
 +    QCOMPARE(qApp->inputMethod()->visible(), false);
 +}
 +
 +class MyTextInput : public QQuickTextInput
 +{
 +public:
 +    MyTextInput(QQuickItem *parent = 0) : QQuickTextInput(parent)
 +    {
 +        nbPaint = 0;
 +    }
 +    virtual QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *data)
 +    {
 +       nbPaint++;
 +       return QQuickTextInput::updatePaintNode(node, data);
 +    }
 +    int nbPaint;
 +};
 +
 +void tst_qquicktextinput::setHAlignClearCache()
 +{
 +    QQuickView view;
 +    MyTextInput input;
 +    input.setText("Hello world");
 +    input.setParentItem(view.rootItem());
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +#ifdef Q_OS_MAC
 +    QEXPECT_FAIL("", "QTBUG-23485", Abort);
 +#endif
 +    QTRY_COMPARE(input.nbPaint, 1);
 +    input.setHAlign(QQuickTextInput::AlignRight);
 +    //Changing the alignment should trigger a repaint
 +    QTRY_COMPARE(input.nbPaint, 2);
 +}
 +
 +void tst_qquicktextinput::focusOutClearSelection()
 +{
 +    QQuickView view;
 +    QQuickTextInput input;
 +    QQuickTextInput input2;
 +    input.setText(QLatin1String("Hello world"));
 +    input.setFocus(true);
 +    input2.setParentItem(view.rootItem());
 +    input.setParentItem(view.rootItem());
 +    input.componentComplete();
 +    input2.componentComplete();
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    input.select(2,5);
 +    //The selection should work
 +    QTRY_COMPARE(input.selectedText(), QLatin1String("llo"));
 +    input2.setFocus(true);
 +    QGuiApplication::processEvents();
 +    //The input lost the focus selection should be cleared
 +    QTRY_COMPARE(input.selectedText(), QLatin1String(""));
 +}
 +
 +void tst_qquicktextinput::geometrySignals()
 +{
 +    QQmlComponent component(&engine, testFileUrl("geometrySignals.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o);
 +    QCOMPARE(o->property("bindingWidth").toInt(), 400);
 +    QCOMPARE(o->property("bindingHeight").toInt(), 500);
 +    delete o;
 +}
 +
 +void tst_qquicktextinput::contentSize()
 +{
 +    QString componentStr = "import QtQuick 2.0\nTextInput { width: 75; height: 16; font.pixelSize: 10 }";
 +    QQmlComponent textComponent(&engine);
 +    textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
 +    QScopedPointer<QObject> object(textComponent.create());
 +    QQuickTextInput *textObject = qobject_cast<QQuickTextInput *>(object.data());
 +
 +    QSignalSpy spy(textObject, SIGNAL(contentSizeChanged()));
 +
 +    textObject->setText("The quick red fox jumped over the lazy brown dog");
 +
 +    QVERIFY(textObject->contentWidth() > textObject->width());
 +    QVERIFY(textObject->contentHeight() < textObject->height());
 +    QCOMPARE(spy.count(), 1);
 +
 +    textObject->setWrapMode(QQuickTextInput::WordWrap);
 +    QVERIFY(textObject->contentWidth() <= textObject->width());
 +    QVERIFY(textObject->contentHeight() > textObject->height());
 +    QCOMPARE(spy.count(), 2);
 +
 +    textObject->setText("The quickredfoxjumpedoverthe lazy brown dog");
 +
 +    QVERIFY(textObject->contentWidth() > textObject->width());
 +    QVERIFY(textObject->contentHeight() > textObject->height());
 +    QCOMPARE(spy.count(), 3);
 +}
 +
 +static void sendPreeditText(const QString &text, int cursor)
 +{
 +    QInputMethodEvent event(text, QList<QInputMethodEvent::Attribute>()
 +            << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor, text.length(), QVariant()));
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &event);
 +}
 +
 +void tst_qquicktextinput::preeditAutoScroll()
 +{
 +    QString preeditText = "califragisiticexpialidocious!";
 +
 +    QQuickView view(testFileUrl("preeditAutoScroll.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
 +    QVERIFY(input);
 +    QVERIFY(input->hasActiveFocus());
 +
 +    input->setWidth(input->implicitWidth());
 +
 +    QSignalSpy cursorRectangleSpy(input, SIGNAL(cursorRectangleChanged()));
 +    int cursorRectangleChanges = 0;
 +
 +    // test the text is scrolled so the preedit is visible.
 +    sendPreeditText(preeditText.mid(0, 3), 1);
 +    QVERIFY(evaluate<int>(input, QString("positionAt(0)")) != 0);
 +    QVERIFY(input->cursorRectangle().left() < input->boundingRect().width());
 +    QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
 +
 +    // test the text is scrolled back when the preedit is removed.
 +    QInputMethodEvent imEvent;
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
 +    QCOMPARE(evaluate<int>(input, QString("positionAt(%1)").arg(0)), 0);
 +    QCOMPARE(evaluate<int>(input, QString("positionAt(%1)").arg(input->width())), 5);
 +    QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
 +
 +    QTextLayout layout(preeditText);
 +    layout.setFont(input->font());
 +    if (!qmlDisableDistanceField()) {
 +        QTextOption option;
 +        option.setUseDesignMetrics(true);
 +        layout.setTextOption(option);
 +    }
 +    layout.beginLayout();
 +    QTextLine line = layout.createLine();
 +    layout.endLayout();
 +
 +    // test if the preedit is larger than the text input that the
 +    // character preceding the cursor is still visible.
 +    qreal x = input->positionToRectangle(0).x();
 +    for (int i = 0; i < 3; ++i) {
 +        sendPreeditText(preeditText, i + 1);
 +        int width = ceil(line.cursorToX(i, QTextLine::Trailing)) - floor(line.cursorToX(i));
 +        QVERIFY(input->cursorRectangle().right() >= width - 3);
 +        QVERIFY(input->positionToRectangle(0).x() < x);
 +        QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
 +        x = input->positionToRectangle(0).x();
 +    }
 +    for (int i = 1; i >= 0; --i) {
 +        sendPreeditText(preeditText, i + 1);
 +        int width = ceil(line.cursorToX(i, QTextLine::Trailing)) - floor(line.cursorToX(i));
 +        QVERIFY(input->cursorRectangle().right() >= width - 3);
 +        QVERIFY(input->positionToRectangle(0).x() > x);
 +        QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
 +        x = input->positionToRectangle(0).x();
 +    }
 +
 +    // Test incrementing the preedit cursor doesn't cause further
 +    // scrolling when right most text is visible.
 +    sendPreeditText(preeditText, preeditText.length() - 3);
 +    QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
 +    x = input->positionToRectangle(0).x();
 +    for (int i = 2; i >= 0; --i) {
 +        sendPreeditText(preeditText, preeditText.length() - i);
 +        QCOMPARE(input->positionToRectangle(0).x(), x);
 +        QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
 +    }
 +    for (int i = 1; i <  3; ++i) {
 +        sendPreeditText(preeditText, preeditText.length() - i);
 +        QCOMPARE(input->positionToRectangle(0).x(), x);
 +        QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
 +    }
 +
 +    // Test disabling auto scroll.
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
 +
 +    input->setAutoScroll(false);
 +    sendPreeditText(preeditText.mid(0, 3), 1);
 +    QCOMPARE(evaluate<int>(input, QString("positionAt(%1)").arg(0)), 0);
 +    QCOMPARE(evaluate<int>(input, QString("positionAt(%1)").arg(input->width())), 5);
 +}
 +
 +void tst_qquicktextinput::preeditCursorRectangle()
 +{
 +    QString preeditText = "super";
 +
 +    QQuickView view(testFileUrl("inputMethodEvent.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
 +    QVERIFY(input);
 +
 +    QRect currentRect;
 +
 +    QInputMethodQueryEvent query(Qt::ImCursorRectangle);
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
 +    QRect previousRect = query.value(Qt::ImCursorRectangle).toRect();
 +
 +    // Verify that the micro focus rect is positioned the same for position 0 as
 +    // it would be if there was no preedit text.
 +    sendPreeditText(preeditText, 0);
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
 +    currentRect = query.value(Qt::ImCursorRectangle).toRect();
 +    QCOMPARE(currentRect, previousRect);
 +
 +    QSignalSpy inputSpy(input, SIGNAL(cursorRectangleChanged()));
 +    QSignalSpy panelSpy(qGuiApp->inputMethod(), SIGNAL(cursorRectangleChanged()));
 +
 +    // Verify that the micro focus rect moves to the left as the cursor position
 +    // is incremented.
 +    for (int i = 1; i <= 5; ++i) {
 +        sendPreeditText(preeditText, i);
 +        QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
 +        currentRect = query.value(Qt::ImCursorRectangle).toRect();
 +        QVERIFY(previousRect.left() < currentRect.left());
 +        QVERIFY(inputSpy.count() > 0); inputSpy.clear();
 +        QVERIFY(panelSpy.count() > 0); panelSpy.clear();
 +        previousRect = currentRect;
 +    }
 +
 +    // Verify that if there is no preedit cursor then the micro focus rect is the
 +    // same as it would be if it were positioned at the end of the preedit text.
 +    sendPreeditText(preeditText, 0);
 +    QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
 +    QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
 +    currentRect = query.value(Qt::ImCursorRectangle).toRect();
 +    QCOMPARE(currentRect, previousRect);
 +    QVERIFY(inputSpy.count() > 0);
 +    QVERIFY(panelSpy.count() > 0);
 +}
 +
 +void tst_qquicktextinput::inputContextMouseHandler()
 +{
 +    PlatformInputContext platformInputContext;
 +    QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
 +    inputMethodPrivate->testContext = &platformInputContext;
 +
 +    QString text = "supercalifragisiticexpialidocious!";
 +    QQuickView view(testFileUrl("inputContext.qml"));
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
 +    QVERIFY(input);
 +
 +    input->setFocus(true);
 +    input->setText("");
 +
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +
 +    QTextLayout layout(text);
 +    layout.setFont(input->font());
 +    if (!qmlDisableDistanceField()) {
 +        QTextOption option;
 +        option.setUseDesignMetrics(true);
 +        layout.setTextOption(option);
 +    }
 +    layout.beginLayout();
 +    QTextLine line = layout.createLine();
 +    layout.endLayout();
 +
 +    const qreal x = line.cursorToX(2, QTextLine::Leading);
 +    const qreal y = line.height() / 2;
 +    QPoint position = QPointF(x, y).toPoint();
 +
 +    QInputMethodEvent inputEvent(text.mid(0, 5), QList<QInputMethodEvent::Attribute>());
 +    QGuiApplication::sendEvent(input, &inputEvent);
 +
 +    QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
 +    QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
 +    QGuiApplication::processEvents();
 +
 +    QCOMPARE(platformInputContext.m_action, QInputMethod::Click);
 +    QCOMPARE(platformInputContext.m_invokeActionCallCount, 1);
 +    QCOMPARE(platformInputContext.m_cursorPosition, 2);
 +}
 +
 +void tst_qquicktextinput::inputMethodComposing()
 +{
 +    QString text = "supercalifragisiticexpialidocious!";
 +
 +    QQuickView view(testFileUrl("inputContext.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
 +    QVERIFY(input);
 +    QSignalSpy spy(input, SIGNAL(inputMethodComposingChanged()));
 +
 +    QCOMPARE(input->isInputMethodComposing(), false);
 +    {
 +        QInputMethodEvent event(text.mid(3), QList<QInputMethodEvent::Attribute>());
 +        QGuiApplication::sendEvent(input, &event);
 +    }
 +    QCOMPARE(input->isInputMethodComposing(), true);
 +    QCOMPARE(spy.count(), 1);
 +
 +    {
 +        QInputMethodEvent event(text.mid(12), QList<QInputMethodEvent::Attribute>());
 +        QGuiApplication::sendEvent(input, &event);
 +    }
 +    QCOMPARE(spy.count(), 1);
 +
 +    {
 +        QInputMethodEvent event;
 +        QGuiApplication::sendEvent(input, &event);
 +    }
 +    QCOMPARE(input->isInputMethodComposing(), false);
 +    QCOMPARE(spy.count(), 2);
 +}
 +
 +void tst_qquicktextinput::inputMethodUpdate()
 +{
 +    PlatformInputContext platformInputContext;
 +    QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
 +    inputMethodPrivate->testContext = &platformInputContext;
 +
 +    QQuickView view(testFileUrl("inputContext.qml"));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
 +    QVERIFY(input);
 +
 +    // text change even without cursor position change needs to trigger update
 +    input->setText("test");
 +    platformInputContext.clear();
 +    input->setText("xxxx");
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // input method event replacing text
 +    platformInputContext.clear();
 +    {
 +        QInputMethodEvent inputMethodEvent;
 +        inputMethodEvent.setCommitString("y", -1, 1);
 +        QGuiApplication::sendEvent(input, &inputMethodEvent);
 +    }
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // input method changing selection
 +    platformInputContext.clear();
 +    {
 +        QList<QInputMethodEvent::Attribute> attributes;
 +        attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 2, QVariant());
 +        QInputMethodEvent inputMethodEvent("", attributes);
 +        QGuiApplication::sendEvent(input, &inputMethodEvent);
 +    }
 +    QVERIFY(input->selectionStart() != input->selectionEnd());
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // programmatical selections trigger update
 +    platformInputContext.clear();
 +    input->selectAll();
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // font changes
 +    platformInputContext.clear();
 +    QFont font = input->font();
 +    font.setBold(!font.bold());
 +    input->setFont(font);
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // normal input
 +    platformInputContext.clear();
 +    {
 +        QInputMethodEvent inputMethodEvent;
 +        inputMethodEvent.setCommitString("y");
 +        QGuiApplication::sendEvent(input, &inputMethodEvent);
 +    }
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // changing cursor position
 +    platformInputContext.clear();
 +    input->setCursorPosition(0);
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +
 +    // read only disabled input method
 +    platformInputContext.clear();
 +    input->setReadOnly(true);
 +    QVERIFY(platformInputContext.m_updateCallCount > 0);
 +    input->setReadOnly(false);
 +
 +    // no updates while no focus
 +    input->setFocus(false);
 +    platformInputContext.clear();
 +    input->setText("Foo");
 +    QCOMPARE(platformInputContext.m_updateCallCount, 0);
 +    input->setCursorPosition(1);
 +    QCOMPARE(platformInputContext.m_updateCallCount, 0);
 +    input->selectAll();
 +    QCOMPARE(platformInputContext.m_updateCallCount, 0);
 +    input->setReadOnly(true);
 +    QCOMPARE(platformInputContext.m_updateCallCount, 0);
 +}
 +
 +void tst_qquicktextinput::cursorRectangleSize()
 +{
 +    QQuickView *canvas = new QQuickView(testFileUrl("positionAt.qml"));
 +    QVERIFY(canvas->rootObject() != 0);
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput *>(canvas->rootObject());
 +
 +    // make sure cursor rectangle is not at (0,0)
 +    textInput->setX(10);
 +    textInput->setY(10);
 +    textInput->setCursorPosition(3);
 +    QVERIFY(textInput != 0);
 +    textInput->setFocus(true);
 +    canvas->show();
 +    canvas->requestActivateWindow();
 +    QTest::qWaitForWindowShown(canvas);
 +    QTRY_VERIFY(qApp->focusObject());
 +
 +    QInputMethodQueryEvent event(Qt::ImCursorRectangle);
 +    qApp->sendEvent(qApp->focusObject(), &event);
 +    QRectF cursorRectFromQuery = event.value(Qt::ImCursorRectangle).toRectF();
 +
-     QCOMPARE(cursorRectFromItem, cursorRectFromQuery.toRect());
++    QRectF cursorRectFromItem = textInput->cursorRectangle();
 +    QRectF cursorRectFromPositionToRectangle = textInput->positionToRectangle(textInput->cursorPosition());
 +
 +    // item and input query cursor rectangles match
-     QCOMPARE(cursorRectFromItem, cursorRectFromPositionToRectangle.toRect());
++    QCOMPARE(cursorRectFromItem, cursorRectFromQuery);
 +
 +    // item cursor rectangle and positionToRectangle calculations match
++    QCOMPARE(cursorRectFromItem, cursorRectFromPositionToRectangle);
 +
 +    // item-canvas transform and input item transform match
 +    QCOMPARE(QQuickItemPrivate::get(textInput)->itemToCanvasTransform(), qApp->inputMethod()->inputItemTransform());
 +
 +    // input panel cursorRectangle property and tranformed item cursor rectangle match
 +    QRectF sceneCursorRect = QQuickItemPrivate::get(textInput)->itemToCanvasTransform().mapRect(cursorRectFromItem);
 +    QCOMPARE(sceneCursorRect, qApp->inputMethod()->cursorRectangle());
 +
 +    delete canvas;
 +}
 +
 +void tst_qquicktextinput::tripleClickSelectsAll()
 +{
 +    QString qmlfile = testFile("positionAt.qml");
 +    QQuickView view(QUrl::fromLocalFile(qmlfile));
 +    view.show();
 +    view.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&view);
 +
 +    QTRY_COMPARE(&view, qGuiApp->focusWindow());
 +
 +    QQuickTextInput* input = qobject_cast<QQuickTextInput*>(view.rootObject());
 +    QVERIFY(input);
 +
 +    QLatin1String hello("Hello world!");
 +    input->setSelectByMouse(true);
 +    input->setText(hello);
 +
 +    // Clicking on the same point inside TextInput three times in a row
 +    // should trigger a triple click, thus selecting all the text.
 +    QPoint pointInside = input->pos().toPoint() + QPoint(2,2);
 +    QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
 +    QTest::mouseClick(&view, Qt::LeftButton, 0, pointInside);
 +    QGuiApplication::processEvents();
 +    QCOMPARE(input->selectedText(), hello);
 +
 +    // Now it simulates user moving the mouse between the second and the third click.
 +    // In this situation, we don't expect a triple click.
 +    QPoint pointInsideButFar = QPoint(input->width(),input->height()) - QPoint(2,2);
 +    QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
 +    QTest::mouseClick(&view, Qt::LeftButton, 0, pointInsideButFar);
 +    QGuiApplication::processEvents();
 +    QVERIFY(input->selectedText().isEmpty());
 +
 +    // And now we press the third click too late, so no triple click event is triggered.
 +    QTest::mouseDClick(&view, Qt::LeftButton, 0, pointInside);
 +    QGuiApplication::processEvents();
 +    QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 1);
 +    QTest::mouseClick(&view, Qt::LeftButton, 0, pointInside);
 +    QGuiApplication::processEvents();
 +    QVERIFY(input->selectedText().isEmpty());
 +}
 +
 +void tst_qquicktextinput::QTBUG_19956_data()
 +{
 +    QTest::addColumn<QString>("url");
 +    QTest::newRow("intvalidator") << "qtbug-19956int.qml";
 +    QTest::newRow("doublevalidator") << "qtbug-19956double.qml";
 +}
 +
 +
 +void tst_qquicktextinput::getText_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<QString>("inputMask");
 +    QTest::addColumn<int>("start");
 +    QTest::addColumn<int>("end");
 +    QTest::addColumn<QString>("expectedText");
 +
 +    QTest::newRow("all plain text")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << standard.at(0).length()
 +            << standard.at(0);
 +
 +    QTest::newRow("plain text sub string")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 12
 +            << standard.at(0).mid(0, 12);
 +
 +    QTest::newRow("plain text sub string reversed")
 +            << standard.at(0)
 +            << QString()
 +            << 12 << 0
 +            << standard.at(0).mid(0, 12);
 +
 +    QTest::newRow("plain text cropped beginning")
 +            << standard.at(0)
 +            << QString()
 +            << -3 << 4
 +            << standard.at(0).mid(0, 4);
 +
 +    QTest::newRow("plain text cropped end")
 +            << standard.at(0)
 +            << QString()
 +            << 23 << standard.at(0).length() + 8
 +            << standard.at(0).mid(23);
 +
 +    QTest::newRow("plain text cropped beginning and end")
 +            << standard.at(0)
 +            << QString()
 +            << -9 << standard.at(0).length() + 4
 +            << standard.at(0);
 +}
 +
 +void tst_qquicktextinput::getText()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(QString, inputMask);
 +    QFETCH(int, start);
 +    QFETCH(int, end);
 +    QFETCH(QString, expectedText);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; inputMask: \"" + inputMask + "\" }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    QCOMPARE(textInput->getText(start, end), expectedText);
 +}
 +
 +void tst_qquicktextinput::insert_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<QString>("inputMask");
 +    QTest::addColumn<int>("selectionStart");
 +    QTest::addColumn<int>("selectionEnd");
 +    QTest::addColumn<int>("insertPosition");
 +    QTest::addColumn<QString>("insertText");
 +    QTest::addColumn<QString>("expectedText");
 +    QTest::addColumn<int>("expectedSelectionStart");
 +    QTest::addColumn<int>("expectedSelectionEnd");
 +    QTest::addColumn<int>("expectedCursorPosition");
 +    QTest::addColumn<bool>("selectionChanged");
 +    QTest::addColumn<bool>("cursorPositionChanged");
 +
 +    QTest::newRow("at cursor position (beginning)")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0 << 0
 +            << QString("Hello")
 +            << QString("Hello") + standard.at(0)
 +            << 5 << 5 << 5
 +            << false << true;
 +
 +    QTest::newRow("at cursor position (end)")
 +            << standard.at(0)
 +            << QString()
 +            << standard.at(0).length() << standard.at(0).length() << standard.at(0).length()
 +            << QString("Hello")
 +            << standard.at(0) + QString("Hello")
 +            << standard.at(0).length() + 5 << standard.at(0).length() + 5 << standard.at(0).length() + 5
 +            << false << true;
 +
 +    QTest::newRow("at cursor position (middle)")
 +            << standard.at(0)
 +            << QString()
 +            << 18 << 18 << 18
 +            << QString("Hello")
 +            << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
 +            << 23 << 23 << 23
 +            << false << true;
 +
 +    QTest::newRow("after cursor position (beginning)")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0 << 18
 +            << QString("Hello")
 +            << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("before cursor position (end)")
 +            << standard.at(0)
 +            << QString()
 +            << standard.at(0).length() << standard.at(0).length() << 18
 +            << QString("Hello")
 +            << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
 +            << standard.at(0).length() + 5 << standard.at(0).length() + 5 << standard.at(0).length() + 5
 +            << false << true;
 +
 +    QTest::newRow("before cursor position (middle)")
 +            << standard.at(0)
 +            << QString()
 +            << 18 << 18 << 0
 +            << QString("Hello")
 +            << QString("Hello") + standard.at(0)
 +            << 23 << 23 << 23
 +            << false << true;
 +
 +    QTest::newRow("after cursor position (middle)")
 +            << standard.at(0)
 +            << QString()
 +            << 18 << 18 << standard.at(0).length()
 +            << QString("Hello")
 +            << standard.at(0) + QString("Hello")
 +            << 18 << 18 << 18
 +            << false << false;
 +
 +    QTest::newRow("before selection")
 +            << standard.at(0)
 +            << QString()
 +            << 14 << 19 << 0
 +            << QString("Hello")
 +            << QString("Hello") + standard.at(0)
 +            << 19 << 24 << 24
 +            << false << true;
 +
 +    QTest::newRow("before reversed selection")
 +            << standard.at(0)
 +            << QString()
 +            << 19 << 14 << 0
 +            << QString("Hello")
 +            << QString("Hello") + standard.at(0)
 +            << 19 << 24 << 19
 +            << false << true;
 +
 +    QTest::newRow("after selection")
 +            << standard.at(0)
 +            << QString()
 +            << 14 << 19 << standard.at(0).length()
 +            << QString("Hello")
 +            << standard.at(0) + QString("Hello")
 +            << 14 << 19 << 19
 +            << false << false;
 +
 +    QTest::newRow("after reversed selection")
 +            << standard.at(0)
 +            << QString()
 +            << 19 << 14 << standard.at(0).length()
 +            << QString("Hello")
 +            << standard.at(0) + QString("Hello")
 +            << 14 << 19 << 14
 +            << false << false;
 +
 +    QTest::newRow("into selection")
 +            << standard.at(0)
 +            << QString()
 +            << 14 << 19 << 18
 +            << QString("Hello")
 +            << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
 +            << 14 << 24 << 24
 +            << true << true;
 +
 +    QTest::newRow("into reversed selection")
 +            << standard.at(0)
 +            << QString()
 +            << 19 << 14 << 18
 +            << QString("Hello")
 +            << standard.at(0).mid(0, 18) + QString("Hello") + standard.at(0).mid(18)
 +            << 14 << 24 << 14
 +            << true << false;
 +
 +    QTest::newRow("rich text into plain text")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0 << 0
 +            << QString("<b>Hello</b>")
 +            << QString("<b>Hello</b>") + standard.at(0)
 +            << 12 << 12 << 12
 +            << false << true;
 +
 +    QTest::newRow("before start")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0 << -3
 +            << QString("Hello")
 +            << standard.at(0)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("past end")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0 << standard.at(0).length() + 3
 +            << QString("Hello")
 +            << standard.at(0)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    const QString inputMask = "009.009.009.009";
 +    const QString ip = "192.168.2.14";
 +
 +    QTest::newRow("mask: at cursor position (beginning)")
 +            << ip
 +            << inputMask
 +            << 0 << 0 << 0
 +            << QString("125")
 +            << QString("125.168.2.14")
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("mask: at cursor position (end)")
 +            << ip
 +            << inputMask
 +            << inputMask.length() << inputMask.length() << inputMask.length()
 +            << QString("8")
 +            << ip
 +            << inputMask.length() << inputMask.length() << inputMask.length()
 +            << false << false;
 +
 +    QTest::newRow("mask: at cursor position (middle)")
 +            << ip
 +            << inputMask
 +            << 6 << 6 << 6
 +            << QString("75.2")
 +            << QString("192.167.5.24")
 +            << 6 << 6 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: after cursor position (beginning)")
 +            << ip
 +            << inputMask
 +            << 0 << 0 << 6
 +            << QString("75.2")
 +            << QString("192.167.5.24")
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("mask: before cursor position (end)")
 +            << ip
 +            << inputMask
 +            << inputMask.length() << inputMask.length() << 6
 +            << QString("75.2")
 +            << QString("192.167.5.24")
 +            << inputMask.length() << inputMask.length() << inputMask.length()
 +            << false << false;
 +
 +    QTest::newRow("mask: before cursor position (middle)")
 +            << ip
 +            << inputMask
 +            << 6 << 6 << 0
 +            << QString("125")
 +            << QString("125.168.2.14")
 +            << 6 << 6 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: after cursor position (middle)")
 +            << ip
 +            << inputMask
 +            << 6 << 6 << 13
 +            << QString("8")
 +            << "192.168.2.18"
 +            << 6 << 6 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: before selection")
 +            << ip
 +            << inputMask
 +            << 6 << 8 << 0
 +            << QString("125")
 +            << QString("125.168.2.14")
 +            << 6 << 8 << 8
 +            << false << false;
 +
 +    QTest::newRow("mask: before reversed selection")
 +            << ip
 +            << inputMask
 +            << 8 << 6 << 0
 +            << QString("125")
 +            << QString("125.168.2.14")
 +            << 6 << 8 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: after selection")
 +            << ip
 +            << inputMask
 +            << 6 << 8 << 13
 +            << QString("8")
 +            << "192.168.2.18"
 +            << 6 << 8 << 8
 +            << false << false;
 +
 +    QTest::newRow("mask: after reversed selection")
 +            << ip
 +            << inputMask
 +            << 8 << 6 << 13
 +            << QString("8")
 +            << "192.168.2.18"
 +            << 6 << 8 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: into selection")
 +            << ip
 +            << inputMask
 +            << 5 << 8 << 6
 +            << QString("75.2")
 +            << QString("192.167.5.24")
 +            << 5 << 8 << 8
 +            << true << false;
 +
 +    QTest::newRow("mask: into reversed selection")
 +            << ip
 +            << inputMask
 +            << 8 << 5 << 6
 +            << QString("75.2")
 +            << QString("192.167.5.24")
 +            << 5 << 8 << 5
 +            << true << false;
 +
 +    QTest::newRow("mask: before start")
 +            << ip
 +            << inputMask
 +            << 0 << 0 << -3
 +            << QString("4")
 +            << ip
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("mask: past end")
 +            << ip
 +            << inputMask
 +            << 0 << 0 << ip.length() + 3
 +            << QString("4")
 +            << ip
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("mask: invalid characters")
 +            << ip
 +            << inputMask
 +            << 0 << 0 << 0
 +            << QString("abc")
 +            << QString("192.168.2.14")
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("mask: mixed validity")
 +            << ip
 +            << inputMask
 +            << 0 << 0 << 0
 +            << QString("a1b2c5")
 +            << QString("125.168.2.14")
 +            << 0 << 0 << 0
 +            << false << false;
 +}
 +
 +void tst_qquicktextinput::insert()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(QString, inputMask);
 +    QFETCH(int, selectionStart);
 +    QFETCH(int, selectionEnd);
 +    QFETCH(int, insertPosition);
 +    QFETCH(QString, insertText);
 +    QFETCH(QString, expectedText);
 +    QFETCH(int, expectedSelectionStart);
 +    QFETCH(int, expectedSelectionEnd);
 +    QFETCH(int, expectedCursorPosition);
 +    QFETCH(bool, selectionChanged);
 +    QFETCH(bool, cursorPositionChanged);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; inputMask: \"" + inputMask + "\" }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    textInput->select(selectionStart, selectionEnd);
 +
 +    QSignalSpy selectionSpy(textInput, SIGNAL(selectedTextChanged()));
 +    QSignalSpy selectionStartSpy(textInput, SIGNAL(selectionStartChanged()));
 +    QSignalSpy selectionEndSpy(textInput, SIGNAL(selectionEndChanged()));
 +    QSignalSpy textSpy(textInput, SIGNAL(textChanged()));
 +    QSignalSpy cursorPositionSpy(textInput, SIGNAL(cursorPositionChanged()));
 +
 +    textInput->insert(insertPosition, insertText);
 +
 +    QCOMPARE(textInput->text(), expectedText);
 +    QCOMPARE(textInput->length(), inputMask.isEmpty() ? expectedText.length() : inputMask.length());
 +
 +    QCOMPARE(textInput->selectionStart(), expectedSelectionStart);
 +    QCOMPARE(textInput->selectionEnd(), expectedSelectionEnd);
 +    QCOMPARE(textInput->cursorPosition(), expectedCursorPosition);
 +
 +    if (selectionStart > selectionEnd)
 +        qSwap(selectionStart, selectionEnd);
 +
 +    QCOMPARE(selectionSpy.count() > 0, selectionChanged);
 +    QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
 +    QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
 +    QCOMPARE(textSpy.count() > 0, text != expectedText);
 +    QCOMPARE(cursorPositionSpy.count() > 0, cursorPositionChanged);
 +}
 +
 +void tst_qquicktextinput::remove_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<QString>("inputMask");
 +    QTest::addColumn<int>("selectionStart");
 +    QTest::addColumn<int>("selectionEnd");
 +    QTest::addColumn<int>("removeStart");
 +    QTest::addColumn<int>("removeEnd");
 +    QTest::addColumn<QString>("expectedText");
 +    QTest::addColumn<int>("expectedSelectionStart");
 +    QTest::addColumn<int>("expectedSelectionEnd");
 +    QTest::addColumn<int>("expectedCursorPosition");
 +    QTest::addColumn<bool>("selectionChanged");
 +    QTest::addColumn<bool>("cursorPositionChanged");
 +
 +    QTest::newRow("from cursor position (beginning)")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0
 +            << 0 << 5
 +            << standard.at(0).mid(5)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("to cursor position (beginning)")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0
 +            << 5 << 0
 +            << standard.at(0).mid(5)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("to cursor position (end)")
 +            << standard.at(0)
 +            << QString()
 +            << standard.at(0).length() << standard.at(0).length()
 +            << standard.at(0).length() << standard.at(0).length() - 5
 +            << standard.at(0).mid(0, standard.at(0).length() - 5)
 +            << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
 +            << false << true;
 +
 +    QTest::newRow("to cursor position (end)")
 +            << standard.at(0)
 +            << QString()
 +            << standard.at(0).length() << standard.at(0).length()
 +            << standard.at(0).length() - 5 << standard.at(0).length()
 +            << standard.at(0).mid(0, standard.at(0).length() - 5)
 +            << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
 +            << false << true;
 +
 +    QTest::newRow("from cursor position (middle)")
 +            << standard.at(0)
 +            << QString()
 +            << 18 << 18
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 18 << 18 << 18
 +            << false << false;
 +
 +    QTest::newRow("to cursor position (middle)")
 +            << standard.at(0)
 +            << QString()
 +            << 23 << 23
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 18 << 18 << 18
 +            << false << true;
 +
 +    QTest::newRow("after cursor position (beginning)")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("before cursor position (end)")
 +            << standard.at(0)
 +            << QString()
 +            << standard.at(0).length() << standard.at(0).length()
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << standard.at(0).length() - 5 << standard.at(0).length() - 5 << standard.at(0).length() - 5
 +            << false << true;
 +
 +    QTest::newRow("before cursor position (middle)")
 +            << standard.at(0)
 +            << QString()
 +            << 23 << 23
 +            << 0 << 5
 +            << standard.at(0).mid(5)
 +            << 18 << 18 << 18
 +            << false << true;
 +
 +    QTest::newRow("after cursor position (middle)")
 +            << standard.at(0)
 +            << QString()
 +            << 18 << 18
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 18 << 18 << 18
 +            << false << false;
 +
 +    QTest::newRow("before selection")
 +            << standard.at(0)
 +            << QString()
 +            << 14 << 19
 +            << 0 << 5
 +            << standard.at(0).mid(5)
 +            << 9 << 14 << 14
 +            << false << true;
 +
 +    QTest::newRow("before reversed selection")
 +            << standard.at(0)
 +            << QString()
 +            << 19 << 14
 +            << 0 << 5
 +            << standard.at(0).mid(5)
 +            << 9 << 14 << 9
 +            << false << true;
 +
 +    QTest::newRow("after selection")
 +            << standard.at(0)
 +            << QString()
 +            << 14 << 19
 +            << standard.at(0).length() - 5 << standard.at(0).length()
 +            << standard.at(0).mid(0, standard.at(0).length() - 5)
 +            << 14 << 19 << 19
 +            << false << false;
 +
 +    QTest::newRow("after reversed selection")
 +            << standard.at(0)
 +            << QString()
 +            << 19 << 14
 +            << standard.at(0).length() - 5 << standard.at(0).length()
 +            << standard.at(0).mid(0, standard.at(0).length() - 5)
 +            << 14 << 19 << 14
 +            << false << false;
 +
 +    QTest::newRow("from selection")
 +            << standard.at(0)
 +            << QString()
 +            << 14 << 24
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 14 << 19 << 19
 +            << true << true;
 +
 +    QTest::newRow("from reversed selection")
 +            << standard.at(0)
 +            << QString()
 +            << 24 << 14
 +            << 18 << 23
 +            << standard.at(0).mid(0, 18) + standard.at(0).mid(23)
 +            << 14 << 19 << 14
 +            << true << false;
 +
 +    QTest::newRow("cropped beginning")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0
 +            << -3 << 4
 +            << standard.at(0).mid(4)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("cropped end")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0
 +            << 23 << standard.at(0).length() + 8
 +            << standard.at(0).mid(0, 23)
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("cropped beginning and end")
 +            << standard.at(0)
 +            << QString()
 +            << 0 << 0
 +            << -9 << standard.at(0).length() + 4
 +            << QString()
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    const QString inputMask = "009.009.009.009";
 +    const QString ip = "192.168.2.14";
 +
 +    QTest::newRow("mask: from cursor position")
 +            << ip
 +            << inputMask
 +            << 6 << 6
 +            << 6 << 9
 +            << QString("192.16..14")
 +            << 6 << 6 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: to cursor position")
 +            << ip
 +            << inputMask
 +            << 6 << 6
 +            << 2 << 6
 +            << QString("19.8.2.14")
 +            << 6 << 6 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: before cursor position")
 +            << ip
 +            << inputMask
 +            << 6 << 6
 +            << 0 << 2
 +            << QString("2.168.2.14")
 +            << 6 << 6 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: after cursor position")
 +            << ip
 +            << inputMask
 +            << 6 << 6
 +            << 12 << 16
 +            << QString("192.168.2.")
 +            << 6 << 6 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: before selection")
 +            << ip
 +            << inputMask
 +            << 6 << 8
 +            << 0 << 2
 +            << QString("2.168.2.14")
 +            << 6 << 8 << 8
 +            << false << false;
 +
 +    QTest::newRow("mask: before reversed selection")
 +            << ip
 +            << inputMask
 +            << 8 << 6
 +            << 0 << 2
 +            << QString("2.168.2.14")
 +            << 6 << 8 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: after selection")
 +            << ip
 +            << inputMask
 +            << 6 << 8
 +            << 12 << 16
 +            << QString("192.168.2.")
 +            << 6 << 8 << 8
 +            << false << false;
 +
 +    QTest::newRow("mask: after reversed selection")
 +            << ip
 +            << inputMask
 +            << 8 << 6
 +            << 12 << 16
 +            << QString("192.168.2.")
 +            << 6 << 8 << 6
 +            << false << false;
 +
 +    QTest::newRow("mask: from selection")
 +            << ip
 +            << inputMask
 +            << 6 << 13
 +            << 8 << 10
 +            << QString("192.168..14")
 +            << 6 << 13 << 13
 +            << true << false;
 +
 +    QTest::newRow("mask: from reversed selection")
 +            << ip
 +            << inputMask
 +            << 13 << 6
 +            << 8 << 10
 +            << QString("192.168..14")
 +            << 6 << 13 << 6
 +            << true << false;
 +
 +    QTest::newRow("mask: cropped beginning")
 +            << ip
 +            << inputMask
 +            << 0 << 0
 +            << -3 << 4
 +            << QString(".168.2.14")
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("mask: cropped end")
 +            << ip
 +            << inputMask
 +            << 0 << 0
 +            << 13 << 28
 +            << QString("192.168.2.1")
 +            << 0 << 0 << 0
 +            << false << false;
 +
 +    QTest::newRow("mask: cropped beginning and end")
 +            << ip
 +            << inputMask
 +            << 0 << 0
 +            << -9 << 28
 +            << QString("...")
 +            << 0 << 0 << 0
 +            << false << false;
 +}
 +
 +void tst_qquicktextinput::remove()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(QString, inputMask);
 +    QFETCH(int, selectionStart);
 +    QFETCH(int, selectionEnd);
 +    QFETCH(int, removeStart);
 +    QFETCH(int, removeEnd);
 +    QFETCH(QString, expectedText);
 +    QFETCH(int, expectedSelectionStart);
 +    QFETCH(int, expectedSelectionEnd);
 +    QFETCH(int, expectedCursorPosition);
 +    QFETCH(bool, selectionChanged);
 +    QFETCH(bool, cursorPositionChanged);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; inputMask: \"" + inputMask + "\" }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    textInput->select(selectionStart, selectionEnd);
 +
 +    QSignalSpy selectionSpy(textInput, SIGNAL(selectedTextChanged()));
 +    QSignalSpy selectionStartSpy(textInput, SIGNAL(selectionStartChanged()));
 +    QSignalSpy selectionEndSpy(textInput, SIGNAL(selectionEndChanged()));
 +    QSignalSpy textSpy(textInput, SIGNAL(textChanged()));
 +    QSignalSpy cursorPositionSpy(textInput, SIGNAL(cursorPositionChanged()));
 +
 +    textInput->remove(removeStart, removeEnd);
 +
 +    QCOMPARE(textInput->text(), expectedText);
 +    QCOMPARE(textInput->length(), inputMask.isEmpty() ? expectedText.length() : inputMask.length());
 +
 +    if (selectionStart > selectionEnd)  //
 +        qSwap(selectionStart, selectionEnd);
 +
 +    QCOMPARE(textInput->selectionStart(), expectedSelectionStart);
 +    QCOMPARE(textInput->selectionEnd(), expectedSelectionEnd);
 +    QCOMPARE(textInput->cursorPosition(), expectedCursorPosition);
 +
 +    QCOMPARE(selectionSpy.count() > 0, selectionChanged);
 +    QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
 +    QCOMPARE(selectionEndSpy.count() > 0, selectionEnd != expectedSelectionEnd);
 +    QCOMPARE(textSpy.count() > 0, text != expectedText);
 +
 +    if (cursorPositionChanged)  //
 +        QVERIFY(cursorPositionSpy.count() > 0);
 +}
 +
 +void tst_qquicktextinput::keySequence_data()
 +{
 +    QTest::addColumn<QString>("text");
 +    QTest::addColumn<QKeySequence>("sequence");
 +    QTest::addColumn<int>("selectionStart");
 +    QTest::addColumn<int>("selectionEnd");
 +    QTest::addColumn<int>("cursorPosition");
 +    QTest::addColumn<QString>("expectedText");
 +    QTest::addColumn<QString>("selectedText");
 +
 +    // standard[0] == "the [4]quick [10]brown [16]fox [20]jumped [27]over [32]the [36]lazy [41]dog"
 +
 +    QTest::newRow("select all")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectAll) << 0 << 0
 +            << 44 << standard.at(0) << standard.at(0);
 +    QTest::newRow("select end of line")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5
 +            << 44 << standard.at(0) << standard.at(0).mid(5);
 +    QTest::newRow("select end of document") // ### Not handled.
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3
 +            << 3 << standard.at(0) << QString();
 +    QTest::newRow("select end of block")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18
 +            << 44 << standard.at(0) << standard.at(0).mid(18);
 +    QTest::newRow("delete end of line")
 +            << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24
 +            << 24 << standard.at(0).mid(0, 24) << QString();
 +    QTest::newRow("move to start of line")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31
 +            << 0 << standard.at(0) << QString();
 +    QTest::newRow("move to start of block")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25
 +            << 0 << standard.at(0) << QString();
 +    QTest::newRow("move to next char")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToNextChar) << 12 << 12
 +            << 13 << standard.at(0) << QString();
 +    QTest::newRow("move to previous char")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3
 +            << 2 << standard.at(0) << QString();
 +    QTest::newRow("select next char")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23
 +            << 24 << standard.at(0) << standard.at(0).mid(23, 1);
 +    QTest::newRow("select previous char")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19
 +            << 18 << standard.at(0) << standard.at(0).mid(18, 1);
 +    QTest::newRow("move to next word")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7
 +            << 10 << standard.at(0) << QString();
 +    QTest::newRow("move to previous word")
 +            << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7
 +            << 4 << standard.at(0) << QString();
 +    QTest::newRow("select previous word")
 +            << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11
 +            << 10 << standard.at(0) << standard.at(0).mid(10, 1);
 +    QTest::newRow("delete (selection)")
 +            << standard.at(0) << QKeySequence(QKeySequence::Delete) << 12 << 15
 +            << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString();
 +    QTest::newRow("delete (no selection)")
 +            << standard.at(0) << QKeySequence(QKeySequence::Delete) << 15 << 15
 +            << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString();
 +    QTest::newRow("delete end of word")
 +            << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfWord) << 24 << 24
 +            << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString();
 +    QTest::newRow("delete start of word")
 +            << standard.at(0) << QKeySequence(QKeySequence::DeleteStartOfWord) << 7 << 7
 +            << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString();
 +}
 +
 +void tst_qquicktextinput::keySequence()
 +{
 +    QFETCH(QString, text);
 +    QFETCH(QKeySequence, sequence);
 +    QFETCH(int, selectionStart);
 +    QFETCH(int, selectionEnd);
 +    QFETCH(int, cursorPosition);
 +    QFETCH(QString, expectedText);
 +    QFETCH(QString, selectedText);
 +
 +    if (sequence.isEmpty()) {
 +        QSKIP("Key sequence is undefined");
 +    }
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; text: \"" + text + "\" }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    QQuickCanvas canvas;
 +    textInput->setParentItem(canvas.rootItem());
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
 +
 +    textInput->select(selectionStart, selectionEnd);
 +
 +    simulateKeys(&canvas, sequence);
 +
 +    QCOMPARE(textInput->cursorPosition(), cursorPosition);
 +    QCOMPARE(textInput->text(), expectedText);
 +    QCOMPARE(textInput->selectedText(), selectedText);
 +}
 +
 +#define NORMAL 0
 +#define REPLACE_UNTIL_END 1
 +
 +void tst_qquicktextinput::undo_data()
 +{
 +    QTest::addColumn<QStringList>("insertString");
 +    QTest::addColumn<IntList>("insertIndex");
 +    QTest::addColumn<IntList>("insertMode");
 +    QTest::addColumn<QStringList>("expectedString");
 +    QTest::addColumn<bool>("use_keys");
 +
 +    for (int i=0; i<2; i++) {
 +        QString keys_str = "keyboard";
 +        bool use_keys = true;
 +        if (i==0) {
 +            keys_str = "insert";
 +            use_keys = false;
 +        }
 +
 +        {
 +            IntList insertIndex;
 +            IntList insertMode;
 +            QStringList insertString;
 +            QStringList expectedString;
 +
 +            insertIndex << -1;
 +            insertMode << NORMAL;
 +            insertString << "1";
 +
 +            insertIndex << -1;
 +            insertMode << NORMAL;
 +            insertString << "5";
 +
 +            insertIndex << 1;
 +            insertMode << NORMAL;
 +            insertString << "3";
 +
 +            insertIndex << 1;
 +            insertMode << NORMAL;
 +            insertString << "2";
 +
 +            insertIndex << 3;
 +            insertMode << NORMAL;
 +            insertString << "4";
 +
 +            expectedString << "12345";
 +            expectedString << "1235";
 +            expectedString << "135";
 +            expectedString << "15";
 +            expectedString << "";
 +
 +            QTest::newRow(QString(keys_str + "_numbers").toLatin1()) <<
 +                insertString <<
 +                insertIndex <<
 +                insertMode <<
 +                expectedString <<
 +                bool(use_keys);
 +        }
 +        {
 +            IntList insertIndex;
 +            IntList insertMode;
 +            QStringList insertString;
 +            QStringList expectedString;
 +
 +            insertIndex << -1;
 +            insertMode << NORMAL;
 +            insertString << "World"; // World
 +
 +            insertIndex << 0;
 +            insertMode << NORMAL;
 +            insertString << "Hello"; // HelloWorld
 +
 +            insertIndex << 0;
 +            insertMode << NORMAL;
 +            insertString << "Well"; // WellHelloWorld
 +
 +            insertIndex << 9;
 +            insertMode << NORMAL;
 +            insertString << "There"; // WellHelloThereWorld;
 +
 +            expectedString << "WellHelloThereWorld";
 +            expectedString << "WellHelloWorld";
 +            expectedString << "HelloWorld";
 +            expectedString << "World";
 +            expectedString << "";
 +
 +            QTest::newRow(QString(keys_str + "_helloworld").toLatin1()) <<
 +                insertString <<
 +                insertIndex <<
 +                insertMode <<
 +                expectedString <<
 +                bool(use_keys);
 +        }
 +        {
 +            IntList insertIndex;
 +            IntList insertMode;
 +            QStringList insertString;
 +            QStringList expectedString;
 +
 +            insertIndex << -1;
 +            insertMode << NORMAL;
 +            insertString << "Ensuring";
 +
 +            insertIndex << -1;
 +            insertMode << NORMAL;
 +            insertString << " instan";
 +
 +            insertIndex << 9;
 +            insertMode << NORMAL;
 +            insertString << "an ";
 +
 +            insertIndex << 10;
 +            insertMode << REPLACE_UNTIL_END;
 +            insertString << " unique instance.";
 +
 +            expectedString << "Ensuring a unique instance.";
 +            expectedString << "Ensuring an instan";
 +            expectedString << "Ensuring instan";
 +            expectedString << "";
 +
 +            QTest::newRow(QString(keys_str + "_patterns").toLatin1()) <<
 +                insertString <<
 +                insertIndex <<
 +                insertMode <<
 +                expectedString <<
 +                bool(use_keys);
 +        }
 +    }
 +}
 +
 +void tst_qquicktextinput::undo()
 +{
 +    QFETCH(QStringList, insertString);
 +    QFETCH(IntList, insertIndex);
 +    QFETCH(IntList, insertMode);
 +    QFETCH(QStringList, expectedString);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { focus: true }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    QQuickCanvas canvas;
 +    textInput->setParentItem(canvas.rootItem());
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
 +
 +    QVERIFY(!textInput->canUndo());
 +
 +    QSignalSpy spy(textInput, SIGNAL(canUndoChanged()));
 +
 +    int i;
 +
 +// STEP 1: First build up an undo history by inserting or typing some strings...
 +    for (i = 0; i < insertString.size(); ++i) {
 +        if (insertIndex[i] > -1)
 +            textInput->setCursorPosition(insertIndex[i]);
 +
 + // experimental stuff
 +        if (insertMode[i] == REPLACE_UNTIL_END) {
 +            textInput->select(insertIndex[i], insertIndex[i] + 8);
 +
 +            // This is what I actually want...
 +            // QTest::keyClick(testWidget, Qt::Key_End, Qt::ShiftModifier);
 +        }
 +
 +        for (int j = 0; j < insertString.at(i).length(); j++)
 +            QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
 +    }
 +
 +    QCOMPARE(spy.count(), 1);
 +
 +// STEP 2: Next call undo several times and see if we can restore to the previous state
 +    for (i = 0; i < expectedString.size() - 1; ++i) {
 +        QCOMPARE(textInput->text(), expectedString[i]);
 +        QVERIFY(textInput->canUndo());
 +        textInput->undo();
 +    }
 +
 +// STEP 3: Verify that we have undone everything
 +    QVERIFY(textInput->text().isEmpty());
 +    QVERIFY(!textInput->canUndo());
 +    QCOMPARE(spy.count(), 2);
 +}
 +
 +void tst_qquicktextinput::redo_data()
 +{
 +    QTest::addColumn<QStringList>("insertString");
 +    QTest::addColumn<IntList>("insertIndex");
 +    QTest::addColumn<QStringList>("expectedString");
 +
 +    {
 +        IntList insertIndex;
 +        QStringList insertString;
 +        QStringList expectedString;
 +
 +        insertIndex << -1;
 +        insertString << "World"; // World
 +        insertIndex << 0;
 +        insertString << "Hello"; // HelloWorld
 +        insertIndex << 0;
 +        insertString << "Well"; // WellHelloWorld
 +        insertIndex << 9;
 +        insertString << "There"; // WellHelloThereWorld;
 +
 +        expectedString << "World";
 +        expectedString << "HelloWorld";
 +        expectedString << "WellHelloWorld";
 +        expectedString << "WellHelloThereWorld";
 +
 +        QTest::newRow("Inserts and setting cursor") << insertString << insertIndex << expectedString;
 +    }
 +}
 +
 +void tst_qquicktextinput::redo()
 +{
 +    QFETCH(QStringList, insertString);
 +    QFETCH(IntList, insertIndex);
 +    QFETCH(QStringList, expectedString);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { focus: true }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    QQuickCanvas canvas;
 +    textInput->setParentItem(canvas.rootItem());
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
 +
 +    QVERIFY(!textInput->canUndo());
 +    QVERIFY(!textInput->canRedo());
 +
 +    QSignalSpy spy(textInput, SIGNAL(canRedoChanged()));
 +
 +    int i;
 +    // inserts the diff strings at diff positions
 +    for (i = 0; i < insertString.size(); ++i) {
 +        if (insertIndex[i] > -1)
 +            textInput->setCursorPosition(insertIndex[i]);
 +        for (int j = 0; j < insertString.at(i).length(); j++)
 +            QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
 +        QVERIFY(textInput->canUndo());
 +        QVERIFY(!textInput->canRedo());
 +    }
 +
 +    QCOMPARE(spy.count(), 0);
 +
 +    // undo everything
 +    while (!textInput->text().isEmpty()) {
 +        QVERIFY(textInput->canUndo());
 +        textInput->undo();
 +        QVERIFY(textInput->canRedo());
 +    }
 +
 +    QCOMPARE(spy.count(), 1);
 +
 +    for (i = 0; i < expectedString.size(); ++i) {
 +        QVERIFY(textInput->canRedo());
 +        textInput->redo();
 +        QCOMPARE(textInput->text() , expectedString[i]);
 +        QVERIFY(textInput->canUndo());
 +    }
 +    QVERIFY(!textInput->canRedo());
 +    QCOMPARE(spy.count(), 2);
 +}
 +
 +void tst_qquicktextinput::undo_keypressevents_data()
 +{
 +    QTest::addColumn<KeyList>("keys");
 +    QTest::addColumn<QStringList>("expectedString");
 +
 +    {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        keys << "AFRAID"
 +                << QKeySequence::MoveToStartOfLine
 +                << "VERY"
 +                << Qt::Key_Left
 +                << Qt::Key_Left
 +                << Qt::Key_Left
 +                << Qt::Key_Left
 +                << "BE"
 +                << QKeySequence::MoveToEndOfLine
 +                << "!";
 +
 +        expectedString << "BEVERYAFRAID!";
 +        expectedString << "BEVERYAFRAID";
 +        expectedString << "VERYAFRAID";
 +        expectedString << "AFRAID";
 +
 +        QTest::newRow("Inserts and moving cursor") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        // inserting '1234'
 +        keys << "1234" << QKeySequence::MoveToStartOfLine
 +                // skipping '12'
 +                << Qt::Key_Right << Qt::Key_Right
 +                // selecting '34'
 +                << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
 +                // deleting '34'
 +                << Qt::Key_Delete;
 +
 +        expectedString << "12";
 +        expectedString << "1234";
 +
 +        QTest::newRow("Inserts,moving,selection and delete") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        // inserting 'AB12'
 +        keys << "AB12"
 +                << QKeySequence::MoveToStartOfLine
 +                // selecting 'AB'
 +                << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
 +                << Qt::Key_Delete
 +                << QKeySequence::Undo
 +                << Qt::Key_Right
 +#ifdef Q_OS_WIN //Mac(?) has a specialcase to handle jumping to the end of a selection
 +                << Qt::Key_Left
 +#endif
 +                << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier)
 +                << Qt::Key_Delete;
 +
 +        expectedString << "AB";
 +        expectedString << "AB12";
 +
 +        QTest::newRow("Inserts,moving,selection, delete and undo") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        // inserting 'ABCD'
 +        keys << "abcd"
 +                //move left two
 +                << Qt::Key_Left << Qt::Key_Left
 +                // inserting '1234'
 +                << "1234"
 +                // selecting '1234'
 +                << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier) << (Qt::Key_Left | Qt::ShiftModifier)
 +                // overwriting '1234' with '5'
 +                << "5"
 +                // undoing deletion of 'AB'
 +                << QKeySequence::Undo
 +                // overwriting '1234' with '6'
 +                << "6";
 +
 +        expectedString << "ab6cd";
 +        // for versions previous to 3.2 we overwrite needed two undo operations
 +        expectedString << "ab1234cd";
 +        expectedString << "abcd";
 +
 +        QTest::newRow("Inserts,moving,selection and undo, removing selection") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        // inserting 'ABC'
 +        keys << "ABC"
 +                // removes 'C'
 +                << Qt::Key_Backspace;
 +
 +        expectedString << "AB";
 +        expectedString << "ABC";
 +
 +        QTest::newRow("Inserts,backspace") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        keys << "ABC"
 +                // removes 'C'
 +                << Qt::Key_Backspace
 +                // inserting 'Z'
 +                << "Z";
 +
 +        expectedString << "ABZ";
 +        expectedString << "AB";
 +        expectedString << "ABC";
 +
 +        QTest::newRow("Inserts,backspace,inserts") << keys << expectedString;
 +    } {
 +        KeyList keys;
 +        QStringList expectedString;
 +
 +        // inserting '123'
 +        keys << "123" << QKeySequence::MoveToStartOfLine
 +            // selecting '123'
 +             << QKeySequence::SelectEndOfLine
 +            // overwriting '123' with 'ABC'
 +             << "ABC";
 +
 +        expectedString << "ABC";
 +        // for versions previous to 3.2 we overwrite needed two undo operations
 +        expectedString << "123";
 +
 +        QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString;
 +    }
 +}
 +
 +void tst_qquicktextinput::undo_keypressevents()
 +{
 +    QFETCH(KeyList, keys);
 +    QFETCH(QStringList, expectedString);
 +
 +    QString componentStr = "import QtQuick 2.0\nTextInput { focus: true }";
 +    QQmlComponent textInputComponent(&engine);
 +    textInputComponent.setData(componentStr.toLatin1(), QUrl());
 +    QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
 +    QVERIFY(textInput != 0);
 +
 +    QQuickCanvas canvas;
 +    textInput->setParentItem(canvas.rootItem());
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
 +
 +    simulateKeys(&canvas, keys);
 +
 +    for (int i = 0; i < expectedString.size(); ++i) {
 +        QCOMPARE(textInput->text() , expectedString[i]);
 +        textInput->undo();
 +    }
 +    QVERIFY(textInput->text().isEmpty());
 +}
 +
 +void tst_qquicktextinput::QTBUG_19956()
 +{
 +    QFETCH(QString, url);
 +
 +    QQuickView canvas(testFileUrl(url));
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QVERIFY(canvas.rootObject() != 0);
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput*>(canvas.rootObject());
 +    QVERIFY(input);
 +    input->setFocus(true);
 +    QVERIFY(input->hasActiveFocus());
 +
 +    QCOMPARE(canvas.rootObject()->property("topvalue").toInt(), 30);
 +    QCOMPARE(canvas.rootObject()->property("bottomvalue").toInt(), 10);
 +    QCOMPARE(canvas.rootObject()->property("text").toString(), QString("20"));
 +    QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
 +
 +    canvas.rootObject()->setProperty("topvalue", 15);
 +    QCOMPARE(canvas.rootObject()->property("topvalue").toInt(), 15);
 +    QVERIFY(!canvas.rootObject()->property("acceptableInput").toBool());
 +
 +    canvas.rootObject()->setProperty("topvalue", 25);
 +    QCOMPARE(canvas.rootObject()->property("topvalue").toInt(), 25);
 +    QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
 +
 +    canvas.rootObject()->setProperty("bottomvalue", 21);
 +    QCOMPARE(canvas.rootObject()->property("bottomvalue").toInt(), 21);
 +    QVERIFY(!canvas.rootObject()->property("acceptableInput").toBool());
 +
 +    canvas.rootObject()->setProperty("bottomvalue", 10);
 +    QCOMPARE(canvas.rootObject()->property("bottomvalue").toInt(), 10);
 +    QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
 +}
 +
 +void tst_qquicktextinput::QTBUG_19956_regexp()
 +{
 +    QUrl url = testFileUrl("qtbug-19956regexp.qml");
 +
 +    QString warning = url.toString() + ":11: Unable to assign [undefined] to QRegExp";
 +    QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
 +
 +    QQuickView canvas(url);
 +    canvas.show();
 +    canvas.requestActivateWindow();
 +    QTest::qWaitForWindowShown(&canvas);
 +    QVERIFY(canvas.rootObject() != 0);
 +    QQuickTextInput *input = qobject_cast<QQuickTextInput*>(canvas.rootObject());
 +    QVERIFY(input);
 +    input->setFocus(true);
 +    QVERIFY(input->hasActiveFocus());
 +
 +    canvas.rootObject()->setProperty("regexvalue", QRegExp("abc"));
 +    QCOMPARE(canvas.rootObject()->property("regexvalue").toRegExp(), QRegExp("abc"));
 +    QCOMPARE(canvas.rootObject()->property("text").toString(), QString("abc"));
 +    QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
 +
 +    canvas.rootObject()->setProperty("regexvalue", QRegExp("abcd"));
 +    QCOMPARE(canvas.rootObject()->property("regexvalue").toRegExp(), QRegExp("abcd"));
 +    QVERIFY(!canvas.rootObject()->property("acceptableInput").toBool());
 +
 +    canvas.rootObject()->setProperty("regexvalue", QRegExp("abc"));
 +    QCOMPARE(canvas.rootObject()->property("regexvalue").toRegExp(), QRegExp("abc"));
 +    QVERIFY(canvas.rootObject()->property("acceptableInput").toBool());
 +}
 +
 +
 +void tst_qquicktextinput::negativeDimensions()
 +{
 +    // Verify this doesn't assert during initialization.
 +    QQmlComponent component(&engine, testFileUrl("negativeDimensions.qml"));
 +    QScopedPointer<QObject> o(component.create());
 +    QVERIFY(o);
 +    QQuickTextInput *input = o->findChild<QQuickTextInput *>("input");
 +    QVERIFY(input);
 +    QCOMPARE(input->width(), qreal(-1));
 +    QCOMPARE(input->height(), qreal(-1));
 +}
 +
 +QTEST_MAIN(tst_qquicktextinput)
 +
 +#include "tst_qquicktextinput.moc"
index 6fba193,0000000..4065dbf
mode 100644,000000..100644
--- /dev/null
@@@ -1,70 -1,0 +1,75 @@@
- !contains(QT_CONFIG, concurrent):PUBLICTESTS -= qqmlpixmapcache
 +TEMPLATE = subdirs
 +
 +PUBLICTESTS += \
 +    examples \
 +    geometry \
 +    nodes \
 +    rendernode \
 +    qquickpixmapcache
 +
 +# This test requires the qtconcurrent module
- !contains(QT_CONFIG,xmlpatterns):PRIVATETESTS -= qqmlxmllistmodel
++!contains(QT_CONFIG, concurrent):PUBLICTESTS -= qquickpixmapcache
 +
 +PRIVATETESTS += \
 +    qquickanimations \
 +    qquickapplication \
 +    qquickbehaviors \
 +    qquickfontloader \
 +    qquickpath \
 +    qquicksmoothedanimation \
 +    qquickspringanimation \
 +    qquickstyledtext \
 +    qquickstates \
 +    qquicksystempalette \
 +    qquicktimer \
 +    qquickxmllistmodel
 +
 +# This test requires the xmlpatterns module
-     qquickdroparea \
++!contains(QT_CONFIG,xmlpatterns):PRIVATETESTS -= qquickxmllistmodel
++
++# FIXME
++# qquickdroparea is disabled because it depends on changes that
++# have not been merged from qtbase/master to qtbase/api_changes yet:
++    #qquickdroparea \
 +
 +QUICKTESTS =  \
 +    qquickaccessible \
 +    qquickanchors \
 +    qquickanimatedimage \
++    qquickanimatedsprite \
 +    qquickborderimage \
 +    qquickcanvas \
 +    qquickdrag \
-     qquickspriteimage \
 +    qquickflickable \
 +    qquickflipable \
 +    qquickfocusscope \
 +    qquickgridview \
 +    qquickimage \
 +    qquickitem \
 +    qquickitem2 \
 +    qquickitemlayer \
 +    qquicklistview \
 +    qquickloader \
 +    qquickmousearea \
 +    qquickmultipointtoucharea \
 +    qquickpathview \
 +    qquickpincharea \
 +    qquickpositioners \
 +    qquickrepeater \
 +    qquickshadereffect \
++    qquickspritesequence \
 +    qquicktext \
 +    qquicktextedit \
 +    qquicktextinput \
 +    qquickvisualdatamodel \
 +    qquickview \
 +    qquickcanvasitem \
 +    qquickscreen \
 +
 +
 +SUBDIRS += $$PUBLICTESTS
 +
 +contains(QT_CONFIG, private_tests) {
 +    SUBDIRS += $$PRIVATETESTS
 +    SUBDIRS += $$QUICKTESTS
 +}
index e940727,0000000..6ab754c
mode 100644,000000..100644
--- /dev/null
@@@ -1,180 -1,0 +1,182 @@@
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#ifndef QQUICKVIEWTESTUTIL_H
 +#define QQUICKVIEWTESTUTIL_H
 +
 +#include <QtQuick/QQuickItem>
 +#include <QtQml/QQmlExpression>
 +#include <QtQml/private/qlistmodelinterface_p.h>
 +#include <QtCore/QAbstractListModel>
 +
 +QT_FORWARD_DECLARE_CLASS(QQuickView)
 +
 +namespace QQuickViewTestUtil
 +{
 +    QQuickView *createView();
 +
 +    void flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration);
 +
 +    QList<int> adjustIndexesForAddDisplaced(const QList<int> &indexes, int index, int count);
 +    QList<int> adjustIndexesForMove(const QList<int> &indexes, int from, int to, int count);
 +    QList<int> adjustIndexesForRemoveDisplaced(const QList<int> &indexes, int index, int count);
 +
 +    struct ListChange {
 +        enum { Inserted, Removed, Moved, SetCurrent, SetContentY } type;
 +        int index;
 +        int count;
 +        int to;     // Move
 +        qreal pos;  // setContentY
 +
 +        static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1, 0.0 }; return c; }
 +        static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1, 0.0 }; return c; }
 +        static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to, 0.0 }; return c; }
 +        static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1, 0.0 }; return c; }
 +        static ListChange setContentY(qreal pos) { ListChange c = { SetContentY, -1, -1, -1, pos }; return c; }
 +    };
 +
 +    class QmlListModel : public QListModelInterface
 +    {
 +        Q_OBJECT
 +    public:
 +        QmlListModel(QObject *parent = 0);
 +        ~QmlListModel();
 +
 +        enum Roles { Name, Number };
 +
 +        QString name(int index) const;
 +        QString number(int index) const;
 +
 +        int count() const;
 +
 +        QList<int> roles() const;
 +        QString toString(int role) const;
 +
 +        QVariant data(int index, int role) const;
 +        QHash<int, QVariant> data(int index, const QList<int> &roles) const;
 +
 +        Q_INVOKABLE void addItem(const QString &name, const QString &number);
 +        void insertItem(int index, const QString &name, const QString &number);
 +        void insertItems(int index, const QList<QPair<QString, QString> > &items);
 +
 +        void removeItem(int index);
 +        void removeItems(int index, int count);
 +
 +        void moveItem(int from, int to);
 +        void moveItems(int from, int to, int count);
 +
 +        void modifyItem(int index, const QString &name, const QString &number);
 +
 +        void clear();
 +
 +        void matchAgainst(const QList<QPair<QString, QString> > &other, const QString &error1, const QString &error2);
 +
 +    private:
 +        QList<QPair<QString,QString> > list;
 +    };
 +
 +    class QaimModel : public QAbstractListModel
 +    {
 +        Q_OBJECT
 +    public:
 +        enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
 +
 +        QaimModel(QObject *parent=0);
 +
 +        int rowCount(const QModelIndex &parent=QModelIndex()) const;
 +        QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
 +
 +        int count() const;
 +        QString name(int index) const;
 +        QString number(int index) const;
 +
 +        Q_INVOKABLE void addItem(const QString &name, const QString &number);
 +        void addItems(const QList<QPair<QString, QString> > &items);
 +        void insertItem(int index, const QString &name, const QString &number);
 +        void insertItems(int index, const QList<QPair<QString, QString> > &items);
 +
 +        void removeItem(int index);
 +        void removeItems(int index, int count);
 +
 +        void moveItem(int from, int to);
 +        void moveItems(int from, int to, int count);
 +
 +        void modifyItem(int idx, const QString &name, const QString &number);
 +
 +        void clear();
 +        void reset();
 +
 +        void matchAgainst(const QList<QPair<QString, QString> > &other, const QString &error1, const QString &error2);
 +
 +    private:
 +        QList<QPair<QString,QString> > list;
 +    };
 +
 +    class ListRange
 +    {
 +    public:
 +        ListRange();
 +        ListRange(const ListRange &other);
 +        ListRange(int start, int end);
 +
 +        ~ListRange();
 +
 +        ListRange operator+(const ListRange &other) const;
 +        bool operator==(const ListRange &other) const;
 +        bool operator!=(const ListRange &other) const;
 +
 +        bool isValid() const;
 +        int count() const;
 +
 +        QList<QPair<QString,QString> > getModelDataValues(const QmlListModel &model);
 +        QList<QPair<QString,QString> > getModelDataValues(const QaimModel &model);
 +
 +        QList<int> indexes;
 +        bool valid;
 +    };
 +}
 +
++Q_DECLARE_METATYPE(QQuickViewTestUtil::QaimModel*)
++Q_DECLARE_METATYPE(QQuickViewTestUtil::ListChange)
 +Q_DECLARE_METATYPE(QList<QQuickViewTestUtil::ListChange>)
 +Q_DECLARE_METATYPE(QQuickViewTestUtil::ListRange)
 +
 +#endif // QQUICKVIEWTESTUTIL_H
index 8450b15,0000000..f2da9b0
mode 100644,000000..100644
--- /dev/null
@@@ -1,51 -1,0 +1,51 @@@
- ** This file is part of the Declarative module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +import QtQuick 2.0
 +
 +Item {
 +    function runtest() {
 +        var a = 0;
 +        for (var ii = 0; ii < 100000; ++ii)
 +            a += Text.RichText;
 +        return a;
 +    }
 +}
index e49bf7e,0000000..0f24112
mode 100644,000000..100644
--- /dev/null
@@@ -1,52 -1,0 +1,52 @@@
- ** This file is part of the Declarative module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +import QtQuick 2.0 as QtQuick
 +
 +QtQuick.Item {
 +    function runtest() {
 +        var a = 0;
 +        for (var ii = 0; ii < 100000; ++ii)
 +            a += QtQuick.Text.RichText;
 +        return a;
 +    }
 +}
 +
index 420f621,0000000..b4a49b1
mode 100644,000000..100644
--- /dev/null
@@@ -1,54 -1,0 +1,54 @@@
- ** This file is part of the Declarative module of the Qt Toolkit.
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
++** This file is part of the QtQml module of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +import QtQuick 2.0
 +import "script.js" as Script
 +import "script2.js" as OtherScript
 +
 +Item {
 +    function runtest() {
 +        var a = 0;
 +        for (var ii = 0; ii < 1000000; ++ii)
 +            a += Script.func();
 +        return a;
 +    }
 +}
 +
index 0000000,0000000..37ef64e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,51 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the QtQml module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import Qt.test 1.0
++
++TestObject {
++    onMySignalWithArgs: {
++        var a = 0;
++        for (var i = 0; i < 10000; ++i)
++            a += n;
++        return a;
++    }
++}
index 0000000,0000000..610fcd0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,54 @@@
++/****************************************************************************
++**
++** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/
++**
++** This file is part of the QtQml module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** GNU Lesser General Public License Usage
++** This file may be used under the terms of the GNU Lesser General Public
++** License version 2.1 as published by the Free Software Foundation and
++** appearing in the file LICENSE.LGPL included in the packaging of this
++** file. Please review the following information to ensure the GNU Lesser
++** General Public License version 2.1 requirements will be met:
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU General
++** Public License version 3.0 as published by the Free Software Foundation
++** and appearing in the file LICENSE.GPL included in the packaging of this
++** file. Please review the following information to ensure the GNU General
++** Public License version 3.0 requirements will be met:
++** http://www.gnu.org/copyleft/gpl.html.
++**
++** Other Usage
++** Alternatively, this file may be used in accordance with the terms and
++** conditions contained in a signed written agreement between you and Nokia.
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++import Qt.test 1.0
++
++TestObject {
++    id: obj
++    property real inc: 3
++
++    onMySignalWithArgs: {
++        var a = 0;
++        for (var i = 0; i < 10000; ++i)
++            a += obj.inc;
++        return a;
++    }
++}
index 88e8d9b,0000000..1f836a8
mode 100644,000000..100644
--- /dev/null
@@@ -1,10 -1,0 +1,11 @@@
- QT += qml qml-private testlib v8-private core-private
 +CONFIG += testcase
 +TEMPLATE = app
 +TARGET = tst_script
 +macx:CONFIG -= app_bundle
 +CONFIG += release
 +
 +SOURCES += tst_script.cpp
 +
++QT += core-private gui-private v8-private qml-private quick-private testlib
++
 +DEFINES += SRCDIR=\\\"$$PWD\\\"
index 204fb94,0000000..e7418d5
mode 100644,000000..100644
--- /dev/null
@@@ -1,803 -1,0 +1,852 @@@
- #include <private/qdeclarativeobjectscriptclass_p.h>
 +/****************************************************************************
 +**
 +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 +** Contact: http://www.qt-project.org/
 +**
 +** This file is part of the test suite of the Qt Toolkit.
 +**
 +** $QT_BEGIN_LICENSE:LGPL$
 +** GNU Lesser General Public License Usage
 +** This file may be used under the terms of the GNU Lesser General Public
 +** License version 2.1 as published by the Free Software Foundation and
 +** appearing in the file LICENSE.LGPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU Lesser
 +** General Public License version 2.1 requirements will be met:
 +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 +**
 +** In addition, as a special exception, Nokia gives you certain additional
 +** rights. These rights are described in the Nokia Qt LGPL Exception
 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 +**
 +** GNU General Public License Usage
 +** Alternatively, this file may be used under the terms of the GNU General
 +** Public License version 3.0 as published by the Free Software Foundation
 +** and appearing in the file LICENSE.GPL included in the packaging of this
 +** file. Please review the following information to ensure the GNU General
 +** Public License version 3.0 requirements will be met:
 +** http://www.gnu.org/copyleft/gpl.html.
 +**
 +** Other Usage
 +** Alternatively, this file may be used in accordance with the terms and
 +** conditions contained in a signed written agreement between you and Nokia.
 +**
 +**
 +**
 +**
 +**
 +**
 +** $QT_END_LICENSE$
 +**
 +****************************************************************************/
 +
 +#include <qtest.h>
 +#include <QQmlEngine>
 +#include <QQmlComponent>
 +#include <private/qqmlengine_p.h>
- #include <QScriptEngine>
- #include <QScriptValue>
 +#include <private/qquickrectangle_p.h>
-     void property_getter();
++#include <QJSEngine>
++#include <QJSValue>
 +
 +class tst_script : public QObject
 +{
 +    Q_OBJECT
 +public:
 +    tst_script() {}
 +
 +private slots:
 +    void initTestCase();
 +
 +    void property_js();
-     void property_getter_qobject();
-     void property_getter_qmetaproperty();
 +    void property_getter_js();
- int TestObject::x() 
++#if 0
++   //no native functions for now
++   void property_getter();
++   void property_getter_qobject();
++   void property_getter_qmetaproperty();
++#endif
 +    void property_qobject();
 +    void property_qmlobject();
 +
 +    void setproperty_js();
 +    void setproperty_qmlobject();
 +
 +    void function_js();
++#if 0
++    //no native functions for now
 +    void function_cpp();
++#endif
 +    void function_qobject();
 +    void function_qmlobject();
 +
 +    void function_args_js();
++#if 0
++    //no native functions for now
 +    void function_args_cpp();
++#endif
 +    void function_args_qobject();
 +    void function_args_qmlobject();
 +
 +    void signal_unconnected();
 +    void signal_qml();
 +    void signal_args();
 +    void signal_unusedArgs();
++    void signal_heavyArgsAccess();
++    void signal_heavyIdAccess();
 +
 +    void slot_simple();
 +    void slot_simple_js();
 +    void slot_complex();
 +    void slot_complex_js();
 +
 +    void block_data();
 +    void block();
 +
 +    void global_property_js();
 +    void global_property_qml();
 +    void global_property_qml_js();
 +
 +    void scriptfile_property();
 +
 +    void enums();
 +    void namespacedEnums();
 +    void scriptCall();
 +};
 +
 +inline QUrl TEST_FILE(const QString &filename)
 +{
 +    return QUrl::fromLocalFile(QLatin1String(SRCDIR) + QLatin1String("/data/") + filename);
 +}
 +
 +class TestObject : public QObject
 +{
 +    Q_OBJECT
 +    Q_PROPERTY(int x READ x WRITE setX)
 +
 +public:
 +    TestObject(QObject *parent = 0);
 +
 +    int x();
 +    void setX(int x) { m_x = x; }
 +
 +    void emitMySignal() { emit mySignal(); }
 +    void emitMySignalWithArgs(int n) { emit mySignalWithArgs(n); }
 +
 +signals:
 +    void mySignal();
 +    void mySignalWithArgs(int n);
 +
 +public slots:
 +    int method() {
 +        return x();
 +    }
 +
 +    int methodArgs(int val) {
 +        return val + x();
 +    }
 +
 +private:
 +    int m_x;
 +};
 +QML_DECLARE_TYPE(TestObject);
 +
 +TestObject::TestObject(QObject *parent)
 +: QObject(parent), m_x(0)
 +{
 +}
 +
-     QScriptEngine engine;
++int TestObject::x()
 +{
 +    return m_x++;
 +}
 +
 +void tst_script::initTestCase()
 +{
 +    qmlRegisterType<TestObject>("Qt.test", 1, 0, "TestObject");
 +}
 +
 +
 +#define PROPERTY_PROGRAM \
 +    "(function(testObject) { return (function() { " \
 +    "    var test = 0; " \
 +    "    for (var ii = 0; ii < 10000; ++ii) { " \
 +    "        test += testObject.x; " \
 +    "    } " \
 +    "    return test; " \
 +    "}); })"
 +
 +void tst_script::property_js()
 +{
-     QScriptValue v = engine.newObject();
++    QJSEngine engine;
 +
-     QScriptValueList args;
++    QJSValue v = engine.newObject();
 +    v.setProperty(QLatin1String("x"), 10);
 +
-     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
- static QScriptValue property_getter_method(QScriptContext *, QScriptEngine *engine) 
++    QJSValue prog = engine.evaluate(PROPERTY_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call().toNumber();
 +    }
 +}
 +
-     return QScriptValue(engine,x++);
++#if 0
++static QJSValue property_getter_method(QScriptContext *, QJSEngine *engine)
 +{
 +    static int x = 0;
-     QScriptEngine engine;
++    return QJSValue(engine,x++);
 +}
 +
 +void tst_script::property_getter()
 +{
-     QScriptValue v = engine.newObject();
-     v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_method), 
-                   QScriptValue::PropertyGetter);
++    QJSEngine engine;
 +
-     QScriptValueList args;
++    QJSValue v = engine.newObject();
++    v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_method),
++                  QJSValue::PropertyGetter);
 +
-     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
- static QScriptValue property_getter_qobject_method(QScriptContext *, QScriptEngine *) 
++    QJSValue prog = engine.evaluate(PROPERTY_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +static TestObject *property_getter_qobject_object = 0;
-     if (idx == -1) 
++static QJSValue property_getter_qobject_method(QScriptContext *, QJSEngine *)
 +{
 +    static int idx = -1;
-     return QScriptValue(value);
++    if (idx == -1)
 +        idx = TestObject::staticMetaObject.indexOfProperty("x");
 +
 +    int value = 0;
 +    void *args[] = { &value, 0 };
 +    QMetaObject::metacall(property_getter_qobject_object, QMetaObject::ReadProperty, idx, args);
 +
- static QScriptValue property_getter_qmetaproperty_method(QScriptContext *, QScriptEngine *) 
++    return QJSValue(value);
 +}
 +
-     if (idx == -1) 
++static QJSValue property_getter_qmetaproperty_method(QScriptContext *, QJSEngine *)
 +{
 +    static int idx = -1;
-     return QScriptValue(value);
++    if (idx == -1)
 +        idx = TestObject::staticMetaObject.indexOfProperty("x");
 +
 +    int value = 0;
 +    value = property_getter_qobject_object->metaObject()->property(idx).read(property_getter_qobject_object).toInt();
 +
-     QScriptEngine engine;
++    return QJSValue(value);
 +}
 +
 +void tst_script::property_getter_qobject()
 +{
-     QScriptValue v = engine.newObject();
-     v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_qobject_method), 
-                   QScriptValue::PropertyGetter);
++    QJSEngine engine;
 +
 +    TestObject to;
 +    property_getter_qobject_object = &to;
-     QScriptValueList args;
++    QJSValue v = engine.newObject();
++    v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_qobject_method),
++                  QJSValue::PropertyGetter);
 +
-     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine engine;
++    QJSValue prog = engine.evaluate(PROPERTY_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +    property_getter_qobject_object = 0;
 +}
 +
 +void tst_script::property_getter_qmetaproperty()
 +{
-     QScriptValue v = engine.newObject();
-     v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_qmetaproperty_method), 
-                   QScriptValue::PropertyGetter);
++    QJSEngine engine;
 +
 +    TestObject to;
 +    property_getter_qobject_object = &to;
-     QScriptValueList args;
++    QJSValue v = engine.newObject();
++    v.setProperty(QLatin1String("x"), engine.newFunction(property_getter_qmetaproperty_method),
++                  QJSValue::PropertyGetter);
 +
-     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
++    QJSValue prog = engine.evaluate(PROPERTY_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +    property_getter_qobject_object = 0;
 +}
-     QScriptEngine engine;
-     
-     QScriptValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.__defineGetter__(\"x\", function() { return this._x++; }); return o; })").call();
++#endif
 +
 +void tst_script::property_getter_js()
 +{
-     QScriptValueList args;
++    QJSEngine engine;
++
++    QJSValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.__defineGetter__(\"x\", function() { return this._x++; }); return o; })").call();
 +
-     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine engine;
++    QJSValue prog = engine.evaluate(PROPERTY_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +void tst_script::property_qobject()
 +{
-     QScriptValue v = engine.newQObject(&to);
++    QJSEngine engine;
 +
 +    TestObject to;
-     QScriptValueList args;
++    QJSValue v = engine.newQObject(&to);
 +
-     QScriptValue prog = engine.evaluate(PROPERTY_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine *engine = QQmlEnginePrivate::getScriptEngine(&qmlengine);
++    QJSValue prog = engine.evaluate(PROPERTY_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +void tst_script::property_qmlobject()
 +{
 +    QQmlEngine qmlengine;
 +
-     QScriptValue v = QQmlEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
-     QScriptValueList args;
 +    TestObject to;
++    QV8Engine *engine = QQmlEnginePrivate::getV8Engine(&qmlengine);
++    v8::HandleScope handle_scope;
++    v8::Context::Scope scope(engine->context());
++    QJSValue v = engine->scriptValueFromInternal(engine->qobjectWrapper()->newQObject(&to));
 +
-     QScriptValue prog = engine->evaluate(PROPERTY_PROGRAM).call(engine->globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine engine;
++    QJSValue prog = qmlengine.evaluate(PROPERTY_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +#define SETPROPERTY_PROGRAM \
 +    "(function(testObject) { return (function() { " \
 +    "    for (var ii = 0; ii < 10000; ++ii) { " \
 +    "        testObject.x = ii; " \
 +    "    } " \
 +    "}); })"
 +
 +void tst_script::setproperty_js()
 +{
-     QScriptValue v = engine.newObject();
++    QJSEngine engine;
 +
-     QScriptValueList args;
++    QJSValue v = engine.newObject();
 +    v.setProperty(QLatin1String("x"), 0);
 +
-     QScriptValue prog = engine.evaluate(SETPROPERTY_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine *engine = QQmlEnginePrivate::getScriptEngine(&qmlengine);
++    QJSValue prog = engine.evaluate(SETPROPERTY_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +void tst_script::setproperty_qmlobject()
 +{
 +    QQmlEngine qmlengine;
 +
-     QScriptValue v = QQmlEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
 +    TestObject to;
 +
-     QScriptValueList args;
++    QV8Engine *engine = QQmlEnginePrivate::getV8Engine(&qmlengine);
++    v8::HandleScope handle_scope;
++    v8::Context::Scope scope(engine->context());
++    QJSValue v = engine->scriptValueFromInternal(engine->qobjectWrapper()->newQObject(&to));
 +
-     QScriptValue prog = engine->evaluate(SETPROPERTY_PROGRAM).call(engine->globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine engine;
-     
-     QScriptValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.method = (function() { return this._x++; }); return o; })").call();
++    QJSValue prog = qmlengine.evaluate(SETPROPERTY_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +#define FUNCTION_PROGRAM \
 +    "(function(testObject) { return (function() { " \
 +    "    var test = 0; " \
 +    "    for (var ii = 0; ii < 10000; ++ii) { " \
 +    "        test += testObject.method(); " \
 +    "    } " \
 +    "    return test; " \
 +    "}); })"
 +
 +void tst_script::function_js()
 +{
-     QScriptValueList args;
++    QJSEngine engine;
++
++    QJSValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.method = (function() { return this._x++; }); return o; })").call();
 +
-     QScriptValue prog = engine.evaluate(FUNCTION_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
- static QScriptValue function_method(QScriptContext *, QScriptEngine *) 
++    QJSValue prog = engine.evaluate(FUNCTION_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
-     return QScriptValue(x++);
++#if 0
++static QJSValue function_method(QScriptContext *, QJSEngine *)
 +{
 +    static int x = 0;
-     QScriptEngine engine;
++    return QJSValue(x++);
 +}
 +
 +void tst_script::function_cpp()
 +{
-     QScriptValue v = engine.newObject();
++    QJSEngine engine;
 +
-     QScriptValueList args;
++    QJSValue v = engine.newObject();
 +    v.setProperty(QLatin1String("method"), engine.newFunction(function_method));
 +
-     QScriptValue prog = engine.evaluate(FUNCTION_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine engine;
++    QJSValue prog = engine.evaluate(FUNCTION_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
++#endif
 +
 +void tst_script::function_qobject()
 +{
-     QScriptValue v = engine.newQObject(&to);
++    QJSEngine engine;
 +
 +    TestObject to;
-     QScriptValueList args;
++    QJSValue v = engine.newQObject(&to);
 +
-     QScriptValue prog = engine.evaluate(FUNCTION_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine *engine = QQmlEnginePrivate::getScriptEngine(&qmlengine);
++    QJSValue prog = engine.evaluate(FUNCTION_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +void tst_script::function_qmlobject()
 +{
 +    QQmlEngine qmlengine;
 +
-     QScriptValue v = QQmlEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
 +    TestObject to;
 +
-     QScriptValueList args;
++    QV8Engine *engine = QQmlEnginePrivate::getV8Engine(&qmlengine);
++    v8::HandleScope handle_scope;
++    v8::Context::Scope scope(engine->context());
++    QJSValue v = engine->scriptValueFromInternal(engine->qobjectWrapper()->newQObject(&to));
 +
-     QScriptValue prog = engine->evaluate(FUNCTION_PROGRAM).call(engine->globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine engine;
-     
-     QScriptValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.methodArgs = (function(a) { return a + this._x++; }); return o; })").call();
++    QJSValue prog = qmlengine.evaluate(FUNCTION_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +#define FUNCTION_ARGS_PROGRAM \
 +    "(function(testObject) { return (function() { " \
 +    "    var test = 0; " \
 +    "    for (var ii = 0; ii < 10000; ++ii) { " \
 +    "        test += testObject.methodArgs(ii); " \
 +    "    } " \
 +    "    return test; " \
 +    "}); })"
 +
 +void tst_script::function_args_js()
 +{
-     QScriptValueList args;
++    QJSEngine engine;
 +
-     QScriptValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(engine.globalObject(), args);
++    QJSValue v = engine.evaluate("(function() { var o = new Object; o._x = 0; o.methodArgs = (function(a) { return a + this._x++; }); return o; })").call();
++
++    QJSValueList args;
 +    args << v;
- static QScriptValue function_args_method(QScriptContext *ctxt, QScriptEngine *) 
++    QJSValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
-     return QScriptValue(ctxt->argument(0).toNumber() + x++);
++#if 0
++static QJSValue function_args_method(QScriptContext *ctxt, QJSEngine *)
 +{
 +    static int x = 0;
-     QScriptEngine engine;
++    return QJSValue(ctxt->argument(0).toNumber() + x++);
 +}
 +
 +void tst_script::function_args_cpp()
 +{
-     QScriptValue v = engine.newObject();
++    QJSEngine engine;
 +
-     QScriptValueList args;
++    QJSValue v = engine.newObject();
 +    v.setProperty(QLatin1String("methodArgs"), engine.newFunction(function_args_method));
 +
-     QScriptValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine engine;
++    QJSValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
++#endif
 +
 +void tst_script::function_args_qobject()
 +{
-     QScriptValue v = engine.newQObject(&to);
++    QJSEngine engine;
 +
 +    TestObject to;
-     QScriptValueList args;
++    QJSValue v = engine.newQObject(&to);
 +
-     QScriptValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(engine.globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine *engine = QQmlEnginePrivate::getScriptEngine(&qmlengine);
++    QJSValue prog = engine.evaluate(FUNCTION_ARGS_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +void tst_script::function_args_qmlobject()
 +{
 +    QQmlEngine qmlengine;
 +
-     QScriptValue v = QQmlEnginePrivate::get(&qmlengine)->objectClass->newQObject(&to);
 +    TestObject to;
 +
-     QScriptValueList args;
++    QV8Engine *engine = QQmlEnginePrivate::getV8Engine(&qmlengine);
++    v8::HandleScope handle_scope;
++    v8::Context::Scope scope(engine->context());
++    QJSValue v = engine->scriptValueFromInternal(engine->qobjectWrapper()->newQObject(&to));
 +
-     QScriptValue prog = engine->evaluate(FUNCTION_ARGS_PROGRAM).call(engine->globalObject(), args);
++    QJSValueList args;
 +    args << v;
-     QScriptEngine engine;
++    QJSValue prog = qmlengine.evaluate(FUNCTION_ARGS_PROGRAM).call(args);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +void tst_script::signal_unconnected()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("signal_unconnected.qml"));
 +    TestObject *object = qobject_cast<TestObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QBENCHMARK {
 +        object->emitMySignal();
 +    }
 +
 +    delete object;
 +}
 +
 +void tst_script::signal_qml()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("signal_qml.qml"));
 +    TestObject *object = qobject_cast<TestObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QBENCHMARK {
 +        object->emitMySignal();
 +    }
 +
 +    delete object;
 +}
 +
 +void tst_script::signal_args()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("signal_args.qml"));
 +    TestObject *object = qobject_cast<TestObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QBENCHMARK {
 +        object->emitMySignalWithArgs(11);
 +    }
 +
 +    delete object;
 +}
 +
 +void tst_script::signal_unusedArgs()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("signal_unusedArgs.qml"));
 +    TestObject *object = qobject_cast<TestObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QBENCHMARK {
 +        object->emitMySignalWithArgs(11);
 +    }
 +
 +    delete object;
 +}
 +
++void tst_script::signal_heavyArgsAccess()
++{
++    QQmlEngine engine;
++    QQmlComponent component(&engine, TEST_FILE("signal_heavyArgsAccess.qml"));
++    TestObject *object = qobject_cast<TestObject *>(component.create());
++    QVERIFY(object != 0);
++
++    QBENCHMARK {
++        object->emitMySignalWithArgs(11);
++    }
++
++    delete object;
++}
++
++void tst_script::signal_heavyIdAccess()
++{
++    QQmlEngine engine;
++    QQmlComponent component(&engine, TEST_FILE("signal_heavyIdAccess.qml"));
++    TestObject *object = qobject_cast<TestObject *>(component.create());
++    QVERIFY(object != 0);
++
++    QBENCHMARK {
++        object->emitMySignalWithArgs(11);
++    }
++
++    delete object;
++}
++
 +void tst_script::slot_simple()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("slot_simple.qml"));
 +    TestObject *object = qobject_cast<TestObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QBENCHMARK {
 +        object->emitMySignal();
 +    }
 +
 +    delete object;
 +}
 +
 +void tst_script::slot_simple_js()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("slot_simple_js.qml"));
 +    TestObject *object = qobject_cast<TestObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QBENCHMARK {
 +        object->emitMySignal();
 +    }
 +
 +    delete object;
 +}
 +
 +void tst_script::slot_complex()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("slot_complex.qml"));
 +    TestObject *object = qobject_cast<TestObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QBENCHMARK {
 +        object->emitMySignal();
 +    }
 +
 +    delete object;
 +}
 +
 +void tst_script::slot_complex_js()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("slot_complex_js.qml"));
 +    TestObject *object = qobject_cast<TestObject *>(component.create());
 +    QVERIFY(object != 0);
 +
 +    QBENCHMARK {
 +        object->emitMySignal();
 +    }
 +
 +    delete object;
 +}
 +
 +void tst_script::block_data()
 +{
 +    QTest::addColumn<QString>("methodName");
 +    QTest::newRow("direct") << "doSomethingDirect()";
 +    QTest::newRow("localObj") << "doSomethingLocalObj()";
 +    QTest::newRow("local") << "doSomethingLocal()";
 +}
 +
 +void tst_script::block()
 +{
 +    QFETCH(QString, methodName);
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("block.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle *>(component.create());
 +    QVERIFY(rect != 0);
 +
 +    int index = rect->metaObject()->indexOfMethod(methodName.toUtf8());
 +    QVERIFY(index != -1);
 +    QMetaMethod method = rect->metaObject()->method(index);
 +
 +    QBENCHMARK {
 +        method.invoke(rect, Qt::DirectConnection);
 +    }
 +
 +    delete rect;
 +}
 +
 +#define GLOBALPROPERTY_PROGRAM \
 +    "(function() { " \
 +    "    for (var ii = 0; ii < 10000; ++ii) { " \
 +    "        Math.sin(90); " \
 +    "    } " \
 +    "})"
 +
 +void tst_script::global_property_js()
 +{
-     QScriptValue prog = engine.evaluate(GLOBALPROPERTY_PROGRAM);
++    QJSEngine engine;
 +
-     QScriptEngine *engine = QQmlEnginePrivate::getScriptEngine(&qmlengine);
-     QScriptValue prog = engine->evaluate(GLOBALPROPERTY_PROGRAM);
++    QJSValue prog = engine.evaluate(GLOBALPROPERTY_PROGRAM);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +void tst_script::global_property_qml()
 +{
 +    QQmlEngine qmlengine;
 +
++    QJSValue prog = qmlengine.evaluate(GLOBALPROPERTY_PROGRAM);
 +    prog.call();
 +
 +    QBENCHMARK {
 +        prog.call();
 +    }
 +}
 +
 +void tst_script::global_property_qml_js()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("global_prop.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle *>(component.create());
 +    QVERIFY(rect != 0);
 +
 +    int index = rect->metaObject()->indexOfMethod("triggered()");
 +    QVERIFY(index != -1);
 +    QMetaMethod method = rect->metaObject()->method(index);
 +
 +    QBENCHMARK {
 +        method.invoke(rect, Qt::DirectConnection);
 +    }
 +
 +    delete rect;
 +}
 +
 +void tst_script::scriptfile_property()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("global_prop.qml"));
 +    QQuickRectangle *rect = qobject_cast<QQuickRectangle *>(component.create());
 +    QVERIFY(rect != 0);
 +
 +    int index = rect->metaObject()->indexOfMethod("incrementTriggered()");
 +    QVERIFY(index != -1);
 +    QMetaMethod method = rect->metaObject()->method(index);
 +
 +    QBENCHMARK {
 +        method.invoke(rect, Qt::DirectConnection);
 +    }
 +
 +    delete rect;
 +}
 +
 +void tst_script::enums()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("enums.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    int index = o->metaObject()->indexOfMethod("runtest()");
 +    QVERIFY(index != -1);
 +    QMetaMethod method = o->metaObject()->method(index);
 +
 +    QBENCHMARK {
 +        method.invoke(o, Qt::DirectConnection);
 +    }
 +
 +    delete o;
 +}
 +
 +void tst_script::namespacedEnums()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("namespacedEnums.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    int index = o->metaObject()->indexOfMethod("runtest()");
 +    QVERIFY(index != -1);
 +    QMetaMethod method = o->metaObject()->method(index);
 +
 +    QBENCHMARK {
 +        method.invoke(o, Qt::DirectConnection);
 +    }
 +
 +    delete o;
 +}
 +
 +void tst_script::scriptCall()
 +{
 +    QQmlEngine engine;
 +    QQmlComponent component(&engine, TEST_FILE("scriptCall.qml"));
 +    QObject *o = component.create();
 +    QVERIFY(o != 0);
 +
 +    int index = o->metaObject()->indexOfMethod("runtest()");
 +    QVERIFY(index != -1);
 +    QMetaMethod method = o->metaObject()->method(index);
 +
 +    QBENCHMARK {
 +        method.invoke(o, Qt::DirectConnection);
 +    }
 +
 +    delete o;
 +}
 +
 +QTEST_MAIN(tst_script)
 +
 +#include "tst_script.moc"
@@@ -133,10 -133,10 +133,10 @@@ public
  };
  
  /* When we dump a QMetaObject, we want to list all the types it is exported as.
--   To do this, we need to find the QDeclarativeTypes associated with this
++   To do this, we need to find the QQmlTypes associated with this
     QMetaObject.
  */
 -static QHash<QByteArray, QSet<const QDeclarativeType *> > qmlTypesByCppName;
 +static QHash<QByteArray, QSet<const QQmlType *> > qmlTypesByCppName;
  
  static QHash<QByteArray, QByteArray> cppToId;
  
@@@ -103,10 -103,10 +103,10 @@@ void ProfileClient::stateChanged(State 
  
  }
  
--class DeclarativeProfileClientPrivate
++class QmlProfileClientPrivate
  {
  public:
--    DeclarativeProfileClientPrivate()
++    QmlProfileClientPrivate()
          : inProgressRanges(0)
          , maximumTime(0)
      {
      qint64 maximumTime;
  };
  
--DeclarativeProfileClient::DeclarativeProfileClient(
 -        QDeclarativeDebugConnection *client)
++QmlProfileClient::QmlProfileClient(
 +        QQmlDebugConnection *client)
      : ProfileClient(QLatin1String("CanvasFrameRate"), client),
--      d(new DeclarativeProfileClientPrivate)
++      d(new QmlProfileClientPrivate)
  {
  }
  
--DeclarativeProfileClient::~DeclarativeProfileClient()
++QmlProfileClient::~QmlProfileClient()
  {
      delete d;
  }
  
--void DeclarativeProfileClient::clearData()
++void QmlProfileClient::clearData()
  {
      ::memset(d->rangeCount, 0,
 -             QDeclarativeProfilerService::MaximumRangeType * sizeof(int));
 +             QQmlProfilerService::MaximumRangeType * sizeof(int));
      ProfileClient::clearData();
  }
  
--void DeclarativeProfileClient::sendRecordingStatus()
++void QmlProfileClient::sendRecordingStatus()
  {
      QByteArray ba;
      QDataStream stream(&ba, QIODevice::WriteOnly);
      sendMessage(ba);
  }
  
--void DeclarativeProfileClient::messageReceived(const QByteArray &data)
++void QmlProfileClient::messageReceived(const QByteArray &data)
  {
      QByteArray rwData = data;
      QDataStream stream(&rwData, QIODevice::ReadOnly);
@@@ -83,13 -83,13 +83,13 @@@ protected
      bool m_enabled;
  };
  
--class DeclarativeProfileClient : public ProfileClient
++class QmlProfileClient : public ProfileClient
  {
      Q_OBJECT
  
  public:
-     DeclarativeProfileClient(QQmlDebugConnection *client);
 -    DeclarativeProfileClient(QDeclarativeDebugConnection *client);
--    ~DeclarativeProfileClient();
++    QmlProfileClient(QQmlDebugConnection *client);
++    ~QmlProfileClient();
  
  public slots:
      void clearData();
@@@ -107,7 -107,7 +107,7 @@@ protected
      virtual void messageReceived(const QByteArray &);
  
  private:
--    class DeclarativeProfileClientPrivate *d;
++    class QmlProfileClientPrivate *d;
  };
  
  class V8ProfileClient : public ProfileClient
@@@ -50,9 -50,9 +50,9 @@@
  
  using namespace Constants;
  
--DeclarativeEvent::DeclarativeEvent()
++QmlEvent::QmlEvent()
  {
 -    eventType = QDeclarativeProfilerService::MaximumRangeType;
 +    eventType = QQmlProfilerService::MaximumRangeType;
      eventId = -1;
      duration = 0;
      calls = 0;
@@@ -64,7 -64,7 +64,7 @@@
      isBindingLoop = false;
  }
  
--DeclarativeEvent::~DeclarativeEvent()
++QmlEvent::~QmlEvent()
  {
      qDeleteAll(parentHash.values());
      parentHash.clear();
@@@ -72,7 -72,7 +72,7 @@@
      childrenHash.clear();
  }
  
--DeclarativeEvent &DeclarativeEvent::operator=(const DeclarativeEvent &ref)
++QmlEvent &QmlEvent::operator=(const QmlEvent &ref)
  {
      if (this == &ref)
          return *this;
      parentHash.clear();
      foreach (const QString &key, ref.parentHash.keys()) {
          parentHash.insert(key,
--                          new DeclarativeEventSub(ref.parentHash.value(key)));
++                          new QmlEventSub(ref.parentHash.value(key)));
      }
  
      qDeleteAll(childrenHash.values());
      childrenHash.clear();
      foreach (const QString &key, ref.childrenHash.keys()) {
          childrenHash.insert(key,
--                            new DeclarativeEventSub(ref.childrenHash.value(key)));
++                            new QmlEventSub(ref.childrenHash.value(key)));
      }
  
      return *this;
@@@ -157,21 -157,21 +157,21 @@@ V8Event &V8Event::operator=(const V8Eve
  }
  
  // endtimedata
--struct DeclarativeEventEndTime {
++struct QmlEventEndTime {
      qint64 endTime;
      int startTimeIndex;
--    DeclarativeEvent *description;
++    QmlEvent *description;
  };
  
  // starttimedata
--struct DeclarativeEventStartTime{
++struct QmlEventStartTime{
      qint64 startTime;
      qint64 length;
      qint64 level;
      int endTimeIndex;
      qint64 nestingLevel;
      qint64 nestingDepth;
--    DeclarativeEvent *description;
++    QmlEvent *description;
  
      // animation-related data
      int frameRate;
      int bindingLoopHead;
  };
  
--struct DeclarativeEventTypeCount {
++struct QmlEventTypeCount {
      QList <int> eventIds;
      int nestingCount;
  };
  
  // used by quicksort
--bool compareEndTimes(const DeclarativeEventEndTime &t1,
--                     const DeclarativeEventEndTime &t2)
++bool compareEndTimes(const QmlEventEndTime &t1,
++                     const QmlEventEndTime &t2)
  {
      return t1.endTime < t2.endTime;
  }
  
--bool compareStartTimes(const DeclarativeEventStartTime &t1,
--                       const DeclarativeEventStartTime &t2)
++bool compareStartTimes(const QmlEventStartTime &t1,
++                       const QmlEventStartTime &t2)
  {
      return t1.startTime < t2.startTime;
  }
  
--bool compareStartIndexes(const DeclarativeEventEndTime &t1,
--                         const DeclarativeEventEndTime &t2)
++bool compareStartIndexes(const QmlEventEndTime &t1,
++                         const QmlEventEndTime &t2)
  {
      return t1.startTimeIndex < t2.startTimeIndex;
  }
  
- QString declarativeEventType(QQmlProfilerService::RangeType typeEnum)
 -QString declarativeEventType(QDeclarativeProfilerService::RangeType typeEnum)
++QString qmlEventType(QQmlProfilerService::RangeType typeEnum)
  {
      switch (typeEnum) {
 -    case QDeclarativeProfilerService::Painting:
 +    case QQmlProfilerService::Painting:
          return QLatin1String(TYPE_PAINTING_STR);
          break;
 -    case QDeclarativeProfilerService::Compiling:
 +    case QQmlProfilerService::Compiling:
          return QLatin1String(TYPE_COMPILING_STR);
          break;
 -    case QDeclarativeProfilerService::Creating:
 +    case QQmlProfilerService::Creating:
          return QLatin1String(TYPE_CREATING_STR);
          break;
 -    case QDeclarativeProfilerService::Binding:
 +    case QQmlProfilerService::Binding:
          return QLatin1String(TYPE_BINDING_STR);
          break;
 -    case QDeclarativeProfilerService::HandlingSignal:
 +    case QQmlProfilerService::HandlingSignal:
          return QLatin1String(TYPE_HANDLINGSIGNAL_STR);
          break;
      default:
      }
  }
  
- QQmlProfilerService::RangeType declarativeEventType(const QString &typeString)
 -QDeclarativeProfilerService::RangeType declarativeEventType(const QString &typeString)
++QQmlProfilerService::RangeType qmlEventType(const QString &typeString)
  {
      if (typeString == QLatin1String(TYPE_PAINTING_STR)) {
 -        return QDeclarativeProfilerService::Painting;
 +        return QQmlProfilerService::Painting;
      } else if (typeString == QLatin1String(TYPE_COMPILING_STR)) {
 -        return QDeclarativeProfilerService::Compiling;
 +        return QQmlProfilerService::Compiling;
      } else if (typeString == QLatin1String(TYPE_CREATING_STR)) {
 -        return QDeclarativeProfilerService::Creating;
 +        return QQmlProfilerService::Creating;
      } else if (typeString == QLatin1String(TYPE_BINDING_STR)) {
 -        return QDeclarativeProfilerService::Binding;
 +        return QQmlProfilerService::Binding;
      } else if (typeString == QLatin1String(TYPE_HANDLINGSIGNAL_STR)) {
 -        return QDeclarativeProfilerService::HandlingSignal;
 +        return QQmlProfilerService::HandlingSignal;
      } else {
          bool isNumber = false;
          int type = typeString.toUInt(&isNumber);
      }
  }
  
--QString getHashStringForDeclarativeEvent(
++QString getHashStringForQmlEvent(
          EventLocation location,
 -        QDeclarativeProfilerService::RangeType eventType)
 +        QQmlProfilerService::RangeType eventType)
  {
      return QString("%1:%2:%3:%4").arg(location.filename,
                                        QString::number(location.line),
@@@ -265,31 -265,31 +265,31 @@@ class ProfileDataPrivat
  public:
  
      // convenience functions
--    void clearDeclarativeRootEvent();
++    void clearQmlRootEvent();
      void clearV8RootEvent();
  
      // Stored data
--    DeclarativeEventHash m_eventDescriptions;
--    QList<DeclarativeEventEndTime> m_endTimeSortedList;
--    QList<DeclarativeEventStartTime> m_startTimeSortedList;
++    QmlEventHash m_eventDescriptions;
++    QList<QmlEventEndTime> m_endTimeSortedList;
++    QList<QmlEventStartTime> m_startTimeSortedList;
  
      void collectV8Statistics();
      V8Events m_v8EventList;
      QHash<int, V8Event *> m_v8parents;
  
--    DeclarativeEvent m_qmlRootEvent;
++    QmlEvent m_qmlRootEvent;
      V8Event m_v8RootEvent;
      QString m_rootEventName;
      QString m_rootEventDesc;
  
--    QHash<int, DeclarativeEventTypeCount *> m_typeCounts;
++    QHash<int, QmlEventTypeCount *> m_typeCounts;
  
      qint64 m_traceEndTime;
      qint64 m_traceStartTime;
      qint64 m_qmlMeasuredTime;
      qint64 m_v8MeasuredTime;
  
--    DeclarativeEventStartTime *m_lastFrameEvent;
++    QmlEventStartTime *m_lastFrameEvent;
      qint64 m_maximumAnimationCount;
      qint64 m_minimumAnimationCount;
  
@@@ -309,7 -309,7 +309,7 @@@ ProfileData::ProfileData(QObject *paren
      d->m_v8MeasuredTime = 0;
      d->m_rootEventName = tr("<program>");
      d->m_rootEventDesc = tr("Main Program");
--    d->clearDeclarativeRootEvent();
++    d->clearQmlRootEvent();
      d->clearV8RootEvent();
      d->m_lastFrameEvent = 0;
      d->m_maximumAnimationCount = 0;
@@@ -334,10 -334,10 +334,10 @@@ void ProfileData::clear(
  
      d->m_v8parents.clear();
  
--    d->clearDeclarativeRootEvent();
++    d->clearQmlRootEvent();
      d->clearV8RootEvent();
  
--    foreach (DeclarativeEventTypeCount *typeCount, d->m_typeCounts.values())
++    foreach (QmlEventTypeCount *typeCount, d->m_typeCounts.values())
          delete typeCount;
      d->m_typeCounts.clear();
  
      emit dataClear();
  }
  
--DeclarativeEvents ProfileData::getDeclarativeEvents() const
++QmlEvents ProfileData::getQmlEvents() const
  {
      return d->m_eventDescriptions.values();
  }
  
--DeclarativeEvent *ProfileData::declarativeEvent(int eventId) const
++QmlEvent *ProfileData::qmlEvent(int eventId) const
  {
--    foreach (DeclarativeEvent *event, d->m_eventDescriptions.values()) {
++    foreach (QmlEvent *event, d->m_eventDescriptions.values()) {
          if (event->eventId == eventId)
              return event;
      }
@@@ -382,8 -382,8 +382,8 @@@ const V8Events& ProfileData::getV8Event
      return d->m_v8EventList;
  }
  
--void ProfileData::addDeclarativeEvent(
 -        QDeclarativeProfilerService::RangeType type, qint64 startTime, qint64 length,
++void ProfileData::addQmlEvent(
 +        QQmlProfilerService::RangeType type, qint64 startTime, qint64 length,
          const QStringList &data, const EventLocation &location)
  {
      const QChar colon = QLatin1Char(':');
      // generate hash
      if (eventLocation.filename.isEmpty()) {
          displayName = tr("<bytecode>");
--        eventHashStr = getHashStringForDeclarativeEvent(eventLocation, type);
++        eventHashStr = getHashStringForQmlEvent(eventLocation, type);
      } else {
          const QString filePath = QUrl(eventLocation.filename).path();
          displayName = filePath.mid(filePath.lastIndexOf(QChar('/')) + 1) + colon + QString::number(eventLocation.line);
--        eventHashStr = getHashStringForDeclarativeEvent(eventLocation, type);
++        eventHashStr = getHashStringForQmlEvent(eventLocation, type);
      }
  
--    DeclarativeEvent *newEvent;
++    QmlEvent *newEvent;
      if (d->m_eventDescriptions.contains(eventHashStr)) {
          newEvent = d->m_eventDescriptions[eventHashStr];
      } else {
--        newEvent = new DeclarativeEvent;
++        newEvent = new QmlEvent;
          newEvent->displayname = displayName;
          newEvent->location = eventLocation;
          newEvent->eventHashStr = eventHashStr;
          d->m_eventDescriptions.insert(eventHashStr, newEvent);
      }
  
--    DeclarativeEventEndTime endTimeData;
++    QmlEventEndTime endTimeData;
      endTimeData.endTime = startTime + length;
      endTimeData.description = newEvent;
      endTimeData.startTimeIndex = d->m_startTimeSortedList.count();
  
--    DeclarativeEventStartTime startTimeData;
++    QmlEventStartTime startTimeData;
      startTimeData.startTime = startTime;
      startTimeData.length = length;
      startTimeData.description = newEvent;
@@@ -537,14 -537,14 +537,14 @@@ void ProfileData::addFrameEvent(qint64 
      displayName = tr("<Animation Update>");
      eventHashStr = displayName;
  
--    DeclarativeEvent *newEvent;
++    QmlEvent *newEvent;
      if (d->m_eventDescriptions.contains(eventHashStr)) {
          newEvent = d->m_eventDescriptions[eventHashStr];
      } else {
--        newEvent = new DeclarativeEvent;
++        newEvent = new QmlEvent;
          newEvent->displayname = displayName;
          newEvent->eventHashStr = eventHashStr;
 -        newEvent->eventType = QDeclarativeProfilerService::Painting;
 +        newEvent->eventType = QQmlProfilerService::Painting;
          newEvent->details = details;
          d->m_eventDescriptions.insert(eventHashStr, newEvent);
      }
                  d->m_lastFrameEvent->startTime + d->m_lastFrameEvent->length;
      }
  
--    DeclarativeEventEndTime endTimeData;
++    QmlEventEndTime endTimeData;
      endTimeData.endTime = time + length;
      endTimeData.description = newEvent;
      endTimeData.startTimeIndex = d->m_startTimeSortedList.count();
  
--    DeclarativeEventStartTime startTimeData;
++    QmlEventStartTime startTimeData;
      startTimeData.startTime = time;
      startTimeData.length = length;
      startTimeData.description = newEvent;
@@@ -645,7 -645,7 +645,7 @@@ void ProfileData::complete(
      postProcess();
  }
  
--void ProfileDataPrivate::clearDeclarativeRootEvent()
++void ProfileDataPrivate::clearQmlRootEvent()
  {
      m_qmlRootEvent.displayname = m_rootEventName;
      m_qmlRootEvent.location = EventLocation();
@@@ -692,7 -692,7 +692,7 @@@ void ProfileData::compileStatistics(qin
      double totalTime = 0;
  
      // clear existing statistics
--    foreach (DeclarativeEvent *eventDescription,
++    foreach (QmlEvent *eventDescription,
               d->m_eventDescriptions.values()) {
          eventDescription->calls = 0;
          // maximum possible value
      }
  
      // create root event for statistics
--    d->clearDeclarativeRootEvent();
++    d->clearQmlRootEvent();
  
      // compute parent-child relationship and call count
--    QHash<int, DeclarativeEvent*> lastParent;
++    QHash<int, QmlEvent*> lastParent;
      for (index = fromIndex; index <= toIndex; index++) {
--        DeclarativeEvent *eventDescription =
++        QmlEvent *eventDescription =
                  d->m_startTimeSortedList[index].description;
  
          if (d->m_startTimeSortedList[index].startTime > endTime ||
  
          int level = d->m_startTimeSortedList[index].level;
  
--        DeclarativeEvent *parentEvent = &d->m_qmlRootEvent;
++        QmlEvent *parentEvent = &d->m_qmlRootEvent;
          if (level > MIN_LEVEL && lastParent.contains(level-1)) {
              parentEvent = lastParent[level-1];
          }
  
          if (!eventDescription->parentHash.contains(parentEvent->eventHashStr)) {
--            DeclarativeEventSub *newParentEvent =
--                    new DeclarativeEventSub(parentEvent);
++            QmlEventSub *newParentEvent =
++                    new QmlEventSub(parentEvent);
              newParentEvent->calls = 1;
              newParentEvent->duration = duration;
  
              eventDescription->parentHash.insert(parentEvent->eventHashStr,
                                                  newParentEvent);
          } else {
--            DeclarativeEventSub *newParentEvent =
++            QmlEventSub *newParentEvent =
                      eventDescription->parentHash.value(parentEvent->eventHashStr);
              newParentEvent->duration += duration;
              newParentEvent->calls++;
          }
  
          if (!parentEvent->childrenHash.contains(eventDescription->eventHashStr)) {
--            DeclarativeEventSub *newChildEvent =
--                    new DeclarativeEventSub(eventDescription);
++            QmlEventSub *newChildEvent =
++                    new QmlEventSub(eventDescription);
              newChildEvent->calls = 1;
              newChildEvent->duration = duration;
  
              parentEvent->childrenHash.insert(eventDescription->eventHashStr,
                                               newChildEvent);
          } else {
--            DeclarativeEventSub *newChildEvent =
++            QmlEventSub *newChildEvent =
                      parentEvent->childrenHash.value(eventDescription->eventHashStr);
              newChildEvent->duration += duration;
              newChildEvent->calls++;
          d->m_qmlRootEvent.calls = 1;
  
      // insert into list
--    DeclarativeEvent *listedRootEvent =
++    QmlEvent *listedRootEvent =
              d->m_eventDescriptions.value(d->m_rootEventName);
      if (!listedRootEvent) {
--        listedRootEvent = new DeclarativeEvent;
++        listedRootEvent = new QmlEvent;
          d->m_eventDescriptions.insert(d->m_rootEventName, listedRootEvent);
      }
      *listedRootEvent = d->m_qmlRootEvent;
  
      // compute percentages
--    foreach (DeclarativeEvent *binding, d->m_eventDescriptions.values()) {
++    foreach (QmlEvent *binding, d->m_eventDescriptions.values()) {
          binding->percentOfTime = binding->duration * 100.0 / totalTime;
          binding->timePerCall = binding->calls > 0 ?
                      double(binding->duration) / binding->calls : 0;
      }
  
      // compute median time
--    QHash < DeclarativeEvent* , QList<qint64> > durationLists;
++    QHash < QmlEvent* , QList<qint64> > durationLists;
      for (index = fromIndex; index <= toIndex; index++) {
--        DeclarativeEvent *desc = d->m_startTimeSortedList[index].description;
++        QmlEvent *desc = d->m_startTimeSortedList[index].description;
          qint64 len = d->m_startTimeSortedList[index].length;
          durationLists[desc].append(len);
      }
--    QMutableHashIterator < DeclarativeEvent* , QList<qint64> > iter(durationLists);
++    QMutableHashIterator < QmlEvent* , QList<qint64> > iter(durationLists);
      while (iter.hasNext()) {
          iter.next();
          if (!iter.value().isEmpty()) {
@@@ -824,16 -824,16 +824,16 @@@ void ProfileData::prepareForDisplay(
  {
      // generate numeric ids
      int ndx = 0;
--    foreach (DeclarativeEvent *binding, d->m_eventDescriptions.values()) {
++    foreach (QmlEvent *binding, d->m_eventDescriptions.values()) {
          binding->eventId = ndx++;
      }
  
      // collect type counts
--    foreach (const DeclarativeEventStartTime &eventStartData,
++    foreach (const QmlEventStartTime &eventStartData,
               d->m_startTimeSortedList) {
          int typeNumber = eventStartData.description->eventType;
          if (!d->m_typeCounts.contains(typeNumber)) {
--            d->m_typeCounts[typeNumber] = new DeclarativeEventTypeCount;
++            d->m_typeCounts[typeNumber] = new QmlEventTypeCount;
              d->m_typeCounts[typeNumber]->nestingCount = 0;
          }
          if (eventStartData.nestingLevel >
@@@ -853,9 -853,9 +853,9 @@@ void ProfileData::sortStartTimes(
  
      // assuming startTimes is partially sorted
      // identify blocks of events and sort them with quicksort
--    QList<DeclarativeEventStartTime>::iterator itFrom =
++    QList<QmlEventStartTime>::iterator itFrom =
              d->m_startTimeSortedList.end() - 2;
--    QList<DeclarativeEventStartTime>::iterator itTo =
++    QList<QmlEventStartTime>::iterator itTo =
              d->m_startTimeSortedList.end() - 1;
  
      while (itFrom != d->m_startTimeSortedList.begin() &&
@@@ -899,9 -899,9 +899,9 @@@ void ProfileData::sortEndTimes(
      if (d->m_endTimeSortedList.count() < 2)
          return;
  
--    QList<DeclarativeEventEndTime>::iterator itFrom =
++    QList<QmlEventEndTime>::iterator itFrom =
              d->m_endTimeSortedList.begin();
--    QList<DeclarativeEventEndTime>::iterator itTo =
++    QList<QmlEventEndTime>::iterator itTo =
              d->m_endTimeSortedList.begin() + 1;
  
      while (itTo != d->m_endTimeSortedList.end() &&
@@@ -1074,9 -1074,9 +1074,9 @@@ void ProfileData::computeLevels(
  void ProfileData::reloadDetails()
  {
      // request binding/signal details from the AST
--    foreach (DeclarativeEvent *event, d->m_eventDescriptions.values()) {
 -        if (event->eventType != QDeclarativeProfilerService::Binding &&
 -                event->eventType != QDeclarativeProfilerService::HandlingSignal)
++    foreach (QmlEvent *event, d->m_eventDescriptions.values()) {
 +        if (event->eventType != QQmlProfilerService::Binding &&
 +                event->eventType != QQmlProfilerService::HandlingSignal)
              continue;
  
          // This skips anonymous bindings in Qt4.8 (we don't have valid location data for them)
  void ProfileData::findBindingLoops(qint64 startTime, qint64 endTime)
  {
      // first clear existing data
--    foreach (DeclarativeEvent *event, d->m_eventDescriptions.values()) {
++    foreach (QmlEvent *event, d->m_eventDescriptions.values()) {
          event->isBindingLoop = false;
--        foreach (DeclarativeEventSub *parentEvent, event->parentHash.values())
++        foreach (QmlEventSub *parentEvent, event->parentHash.values())
              parentEvent->inLoopPath = false;
--        foreach (DeclarativeEventSub *childEvent, event->childrenHash.values())
++        foreach (QmlEventSub *childEvent, event->childrenHash.values())
              childEvent->inLoopPath = false;
      }
  
--    QList <DeclarativeEvent *> stackRefs;
--    QList <DeclarativeEventStartTime *> stack;
++    QList <QmlEvent *> stackRefs;
++    QList <QmlEventStartTime *> stack;
      int fromIndex = findFirstIndex(startTime);
      int toIndex = findLastIndex(endTime);
  
      for (int i = 0; i < d->m_startTimeSortedList.count(); i++) {
--        DeclarativeEvent *currentEvent = d->m_startTimeSortedList[i].description;
--        DeclarativeEventStartTime *inTimeEvent = &d->m_startTimeSortedList[i];
++        QmlEvent *currentEvent = d->m_startTimeSortedList[i].description;
++        QmlEventStartTime *inTimeEvent = &d->m_startTimeSortedList[i];
          inTimeEvent->bindingLoopHead = -1;
  
          // managing call stack
                  // for the statistics
                  currentEvent->isBindingLoop = true;
                  for (int j = stackRefs.indexOf(currentEvent); j < stackRefs.count()-1; j++) {
--                    DeclarativeEventSub *nextEventSub = stackRefs[j]->childrenHash.value(stackRefs[j+1]->eventHashStr);
++                    QmlEventSub *nextEventSub = stackRefs[j]->childrenHash.value(stackRefs[j+1]->eventHashStr);
                      nextEventSub->inLoopPath = true;
--                    DeclarativeEventSub *prevEventSub = stackRefs[j+1]->parentHash.value(stackRefs[j]->eventHashStr);
++                    QmlEventSub *prevEventSub = stackRefs[j+1]->parentHash.value(stackRefs[j]->eventHashStr);
                      prevEventSub->inLoopPath = true;
                  }
              }
  
              // use crossed references to find index in starttimesortedlist
--            DeclarativeEventStartTime *head = stack[stackRefs.indexOf(currentEvent)];
++            QmlEventStartTime *head = stack[stackRefs.indexOf(currentEvent)];
              inTimeEvent->bindingLoopHead = d->m_endTimeSortedList[head->endTimeIndex].startTimeIndex;
              d->m_startTimeSortedList[inTimeEvent->bindingLoopHead].bindingLoopHead = i;
          }
  }
  
  void ProfileData::rewriteDetailsString(
 -        QDeclarativeProfilerService::RangeType eventType,
 +        QQmlProfilerService::RangeType eventType,
          const EventLocation &location, const QString &newString)
  {
--    QString eventHashStr = getHashStringForDeclarativeEvent(location,
++    QString eventHashStr = getHashStringForQmlEvent(location,
                                                              eventType);
      Q_ASSERT(d->m_eventDescriptions.contains(eventHashStr));
      d->m_eventDescriptions.value(eventHashStr)->details = newString;
@@@ -1293,7 -1293,7 +1293,7 @@@ qint64 ProfileData::traceDuration() con
      return traceEndTime() - traceStartTime();
  }
  
--qint64 ProfileData::declarativeMeasuredTime() const
++qint64 ProfileData::qmlMeasuredTime() const
  {
      return d->m_qmlMeasuredTime;
  }
@@@ -1336,14 -1336,14 +1336,14 @@@ bool ProfileData::save(const QString &f
      stream.writeStartElement("eventData");
      stream.writeAttribute("totalTime", QString::number(d->m_qmlMeasuredTime));
  
--    foreach (const DeclarativeEvent *eventData, d->m_eventDescriptions.values()) {
++    foreach (const QmlEvent *eventData, d->m_eventDescriptions.values()) {
          stream.writeStartElement("event");
          stream.writeAttribute("index",
                                QString::number(
                                    d->m_eventDescriptions.keys().indexOf(
                                        eventData->eventHashStr)));
          stream.writeTextElement("displayname", eventData->displayname);
--        stream.writeTextElement("type", declarativeEventType(eventData->eventType));
++        stream.writeTextElement("type", qmlEventType(eventData->eventType));
          if (!eventData->location.filename.isEmpty()) {
              stream.writeTextElement("filename", eventData->location.filename);
              stream.writeTextElement("line",
      stream.writeEndElement(); // eventData
  
      stream.writeStartElement("eventList");
--    foreach (const DeclarativeEventStartTime &rangedEvent,
++    foreach (const QmlEventStartTime &rangedEvent,
               d->m_startTimeSortedList) {
          stream.writeStartElement("range");
          stream.writeAttribute("startTime", QString::number(rangedEvent.startTime));
@@@ -1453,8 -1453,8 +1453,8 @@@ void ProfileData::load(
  
      bool readingQmlEvents = false;
      bool readingV8Events = false;
--    QHash <int, DeclarativeEvent *> descriptionBuffer;
--    DeclarativeEvent *currentEvent = 0;
++    QHash <int, QmlEvent *> descriptionBuffer;
++    QmlEvent *currentEvent = 0;
      QHash <int, V8Event *> v8eventBuffer;
      QHash <int, QString> childrenIndexes;
      QHash <int, QString> childrenTimes;
              }
  
              if (elementName == "range") {
--                DeclarativeEventStartTime rangedEvent;
++                QmlEventStartTime rangedEvent;
                  QXmlStreamAttributes attributes = stream.attributes();
                  if (attributes.hasAttribute("startTime"))
                      rangedEvent.startTime = attributes.value("startTime").
                  if (attributes.hasAttribute("eventIndex")) {
                      int ndx = attributes.value("eventIndex").toString().toInt();
                      if (!descriptionBuffer.value(ndx))
--                        descriptionBuffer[ndx] = new DeclarativeEvent;
++                        descriptionBuffer[ndx] = new QmlEvent;
                      rangedEvent.description = descriptionBuffer.value(ndx);
                  }
                  rangedEvent.endTimeIndex = d->m_endTimeSortedList.length();
                      startTimesAreSorted = false;
                  d->m_startTimeSortedList << rangedEvent;
  
--                DeclarativeEventEndTime endTimeEvent;
++                QmlEventEndTime endTimeEvent;
                  endTimeEvent.endTime = rangedEvent.startTime + rangedEvent.length;
                  endTimeEvent.startTimeIndex = d->m_startTimeSortedList.length()-1;
                  endTimeEvent.description = rangedEvent.description;
                      if (attributes.hasAttribute("index")) {
                          int ndx = attributes.value("index").toString().toInt();
                          if (!descriptionBuffer.value(ndx))
--                            descriptionBuffer[ndx] = new DeclarativeEvent;
++                            descriptionBuffer[ndx] = new QmlEvent;
                          currentEvent = descriptionBuffer[ndx];
                      } else {
                          currentEvent = 0;
                      break;
                  }
                  if (elementName == "type") {
--                    currentEvent->eventType = declarativeEventType(readData);
++                    currentEvent->eventType = qmlEventType(readData);
                      break;
                  }
                  if (elementName == "filename") {
          d->m_v8MeasuredTime = cumulatedV8Time;
  
      // move the buffered data to the details cache
--    foreach (DeclarativeEvent *desc, descriptionBuffer.values()) {
--        desc->eventHashStr = getHashStringForDeclarativeEvent(
++    foreach (QmlEvent *desc, descriptionBuffer.values()) {
++        desc->eventHashStr = getHashStringForQmlEvent(
                      desc->location, desc->eventType);;
          d->m_eventDescriptions[desc->eventHashStr] = desc;
      }
          qSort(d->m_startTimeSortedList.begin(),
                d->m_startTimeSortedList.end(), compareStartTimes);
          for (int i = 0; i< d->m_startTimeSortedList.length(); i++) {
--            DeclarativeEventStartTime startTimeData = d->m_startTimeSortedList[i];
++            QmlEventStartTime startTimeData = d->m_startTimeSortedList[i];
              d->m_endTimeSortedList[startTimeData.endTimeIndex].startTimeIndex = i;
          }
          qSort(d->m_endTimeSortedList.begin(),
  #include <QtCore/QObject>
  #include <QtCore/QHash>
  
--struct DeclarativeEvent;
++struct QmlEvent;
  struct V8Event;
  
--typedef QHash<QString, DeclarativeEvent *> DeclarativeEventHash;
--typedef QList<DeclarativeEvent *> DeclarativeEvents;
++typedef QHash<QString, QmlEvent *> QmlEventHash;
++typedef QList<QmlEvent *> QmlEvents;
  typedef QList<V8Event *> V8Events;
  
  struct EventLocation
      int column;
  };
  
--struct DeclarativeEventSub {
--    DeclarativeEventSub(DeclarativeEvent *from)
++struct QmlEventSub {
++    QmlEventSub(QmlEvent *from)
          : reference(from), duration(0), calls(0), inLoopPath(false)
      {}
--    DeclarativeEventSub(DeclarativeEventSub *from)
++    QmlEventSub(QmlEventSub *from)
          : reference(from->reference), duration(from->duration),
            calls(from->calls), inLoopPath(from->inLoopPath)
      {}
--    DeclarativeEvent *reference;
++    QmlEvent *reference;
      qint64 duration;
      qint64 calls;
      bool inLoopPath;
  };
  
--struct DeclarativeEvent
++struct QmlEvent
  {
--    DeclarativeEvent();
--    ~DeclarativeEvent();
++    QmlEvent();
++    ~QmlEvent();
  
      QString displayname;
      QString eventHashStr;
      QString details;
      EventLocation location;
 -    QDeclarativeProfilerService::RangeType eventType;
 -    QHash <QString, DeclarativeEventSub *> parentHash;
 -    QHash <QString, DeclarativeEventSub *> childrenHash;
 +    QQmlProfilerService::RangeType eventType;
-     QHash <QString, DeclarativeEventSub *> parentHash;
-     QHash <QString, DeclarativeEventSub *> childrenHash;
++    QHash <QString, QmlEventSub *> parentHash;
++    QHash <QString, QmlEventSub *> childrenHash;
      qint64 duration;
      qint64 calls;
      qint64 minTime;
      int eventId;
      bool isBindingLoop;
  
--    DeclarativeEvent &operator=(const DeclarativeEvent &ref);
++    QmlEvent &operator=(const QmlEvent &ref);
  };
  
  struct V8EventSub {
@@@ -143,8 -143,8 +143,8 @@@ public
      explicit ProfileData(QObject *parent = 0);
      ~ProfileData();
  
--    DeclarativeEvents getDeclarativeEvents() const;
--    DeclarativeEvent *declarativeEvent(int eventId) const;
++    QmlEvents getQmlEvents() const;
++    QmlEvent *qmlEvent(int eventId) const;
      const V8Events& getV8Events() const;
      V8Event *v8Event(int eventId) const;
  
      Q_INVOKABLE qint64 traceStartTime() const;
      Q_INVOKABLE qint64 traceEndTime() const;
      Q_INVOKABLE qint64 traceDuration() const;
--    Q_INVOKABLE qint64 declarativeMeasuredTime() const;
++    Q_INVOKABLE qint64 qmlMeasuredTime() const;
      Q_INVOKABLE qint64 v8MeasuredTime() const;
  
      void showErrorDialog(const QString &st ) const;
@@@ -205,7 -205,7 +205,7 @@@ signals
  
  public slots:
      void clear();
-     void addDeclarativeEvent(QQmlProfilerService::RangeType type,
 -    void addDeclarativeEvent(QDeclarativeProfilerService::RangeType type,
++    void addQmlEvent(QQmlProfilerService::RangeType type,
                               qint64 startTime, qint64 length,
                               const QStringList &data,
                               const EventLocation &location);
@@@ -89,10 -89,10 +89,10 @@@ QmlProfilerApplication::QmlProfilerAppl
      m_port(3768),
      m_verbose(false),
      m_quitAfterSave(false),
--    m_declarativeProfilerClient(&m_connection),
++    m_qmlProfilerClient(&m_connection),
      m_v8profilerClient(&m_connection),
      m_connectionAttempts(0),
--    m_declarativeDataReady(false),
++    m_qmlDataReady(false),
      m_v8DataReady(false)
  {
      m_connectTimer.setInterval(1000);
      connect(&m_connection, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(connectionStateChanged(QAbstractSocket::SocketState)));
      connect(&m_connection, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectionError(QAbstractSocket::SocketError)));
  
--    connect(&m_declarativeProfilerClient, SIGNAL(enabledChanged()), this, SLOT(traceClientEnabled()));
--    connect(&m_declarativeProfilerClient, SIGNAL(recordingChanged(bool)), this, SLOT(recordingChanged()));
-     connect(&m_declarativeProfilerClient, SIGNAL(range(QQmlProfilerService::RangeType,qint64,qint64,QStringList,EventLocation)),
-             &m_profileData, SLOT(addDeclarativeEvent(QQmlProfilerService::RangeType,qint64,qint64,QStringList,EventLocation)));
 -    connect(&m_declarativeProfilerClient, SIGNAL(range(QDeclarativeProfilerService::RangeType,qint64,qint64,QStringList,EventLocation)),
 -            &m_profileData, SLOT(addDeclarativeEvent(QDeclarativeProfilerService::RangeType,qint64,qint64,QStringList,EventLocation)));
--    connect(&m_declarativeProfilerClient, SIGNAL(traceFinished(qint64)), &m_profileData, SLOT(setTraceEndTime(qint64)));
--    connect(&m_declarativeProfilerClient, SIGNAL(traceStarted(qint64)), &m_profileData, SLOT(setTraceStartTime(qint64)));
--    connect(&m_declarativeProfilerClient, SIGNAL(frame(qint64,int,int)), &m_profileData, SLOT(addFrameEvent(qint64,int,int)));
--    connect(&m_declarativeProfilerClient, SIGNAL(complete()), this, SLOT(declarativeComplete()));
++    connect(&m_qmlProfilerClient, SIGNAL(enabledChanged()), this, SLOT(traceClientEnabled()));
++    connect(&m_qmlProfilerClient, SIGNAL(recordingChanged(bool)), this, SLOT(recordingChanged()));
++    connect(&m_qmlProfilerClient, SIGNAL(range(QQmlProfilerService::RangeType,qint64,qint64,QStringList,EventLocation)),
++            &m_profileData, SLOT(addQmlEvent(QQmlProfilerService::RangeType,qint64,qint64,QStringList,EventLocation)));
++    connect(&m_qmlProfilerClient, SIGNAL(traceFinished(qint64)), &m_profileData, SLOT(setTraceEndTime(qint64)));
++    connect(&m_qmlProfilerClient, SIGNAL(traceStarted(qint64)), &m_profileData, SLOT(setTraceStartTime(qint64)));
++    connect(&m_qmlProfilerClient, SIGNAL(frame(qint64,int,int)), &m_profileData, SLOT(addFrameEvent(qint64,int,int)));
++    connect(&m_qmlProfilerClient, SIGNAL(complete()), this, SLOT(qmlComplete()));
  
      connect(&m_v8profilerClient, SIGNAL(enabledChanged()), this, SLOT(profilerClientEnabled()));
      connect(&m_v8profilerClient, SIGNAL(range(int,QString,QString,int,double,double)),
@@@ -157,7 -157,7 +157,7 @@@ bool QmlProfilerApplication::parseArgum
                  return false;
              }
          } else if (arg == QLatin1String("-fromStart")) {
--            m_declarativeProfilerClient.setRecording(true);
++            m_qmlProfilerClient.setRecording(true);
              m_v8profilerClient.setRecording(true);
          } else if (arg == QLatin1String("-help") || arg == QLatin1String("-h") || arg == QLatin1String("/h") || arg == QLatin1String("/?")) {
              return false;
@@@ -232,19 -232,19 +232,19 @@@ void QmlProfilerApplication::userComman
          printCommands();
      } else if (cmd == Constants::CMD_RECORD
                 || cmd == Constants::CMD_RECORD2) {
--        m_declarativeProfilerClient.setRecording(
--                    !m_declarativeProfilerClient.isRecording());
++        m_qmlProfilerClient.setRecording(
++                    !m_qmlProfilerClient.isRecording());
          m_v8profilerClient.setRecording(!m_v8profilerClient.isRecording());
--        m_declarativeDataReady = false;
++        m_qmlDataReady = false;
          m_v8DataReady = false;
      } else if (cmd == Constants::CMD_QUIT
                 || cmd == Constants::CMD_QUIT2) {
          print(QLatin1String("Quit"));
--        if (m_declarativeProfilerClient.isRecording()) {
++        if (m_qmlProfilerClient.isRecording()) {
              m_quitAfterSave = true;
--            m_declarativeDataReady = false;
++            m_qmlDataReady = false;
              m_v8DataReady = false;
--            m_declarativeProfilerClient.setRecording(false);
++            m_qmlProfilerClient.setRecording(false);
              m_v8profilerClient.setRecording(false);
          } else {
              quit();
@@@ -304,7 -304,7 +304,7 @@@ void QmlProfilerApplication::connected(
                                  "(type 'help'' to show list of commands).")
                    ).arg(m_hostName).arg((m_port)));
      QString recordingStatus(QLatin1String("Recording Status: %1"));
--    if (!m_declarativeProfilerClient.isRecording() &&
++    if (!m_qmlProfilerClient.isRecording() &&
              !m_v8profilerClient.isRecording())
          recordingStatus = recordingStatus.arg(QLatin1String("Off"));
      else
@@@ -340,7 -340,7 +340,7 @@@ void QmlProfilerApplication::processFin
      if (m_process->exitStatus() == QProcess::NormalExit) {
          logStatus(QString("Process exited (%1).").arg(m_process->exitCode()));
  
--        if (m_declarativeProfilerClient.isRecording()) {
++        if (m_qmlProfilerClient.isRecording()) {
              logError("Process exited while recording, last trace is lost!");
              exit(2);
          } else {
@@@ -357,7 -357,7 +357,7 @@@ void QmlProfilerApplication::traceClien
      logStatus("Trace client is attached.");
      // blocked server is waiting for recording message from both clients
      // once the last one is connected, both messages should be sent
--    m_declarativeProfilerClient.sendRecordingStatus();
++    m_qmlProfilerClient.sendRecordingStatus();
      m_v8profilerClient.sendRecordingStatus();
  }
  
@@@ -367,7 -367,7 +367,7 @@@ void QmlProfilerApplication::profilerCl
  
      // blocked server is waiting for recording message from both clients
      // once the last one is connected, both messages should be sent
--    m_declarativeProfilerClient.sendRecordingStatus();
++    m_qmlProfilerClient.sendRecordingStatus();
      m_v8profilerClient.sendRecordingStatus();
  }
  
@@@ -384,7 -384,7 +384,7 @@@ void QmlProfilerApplication::traceFinis
  
  void QmlProfilerApplication::recordingChanged()
  {
--    if (m_declarativeProfilerClient.isRecording()) {
++    if (m_qmlProfilerClient.isRecording()) {
          print(QLatin1String("Recording is on."));
      } else {
          print(QLatin1String("Recording is off."));
@@@ -411,22 -411,22 +411,22 @@@ void QmlProfilerApplication::logStatus(
      err << status << endl;
  }
  
--void QmlProfilerApplication::declarativeComplete()
++void QmlProfilerApplication::qmlComplete()
  {
--    m_declarativeDataReady = true;
 -    if (m_v8profilerClient.state() != QDeclarativeDebugClient::Enabled ||
++    m_qmlDataReady = true;
 +    if (m_v8profilerClient.state() != QQmlDebugClient::Enabled ||
              m_v8DataReady) {
          m_profileData.complete();
          // once complete is sent, reset the flag
--        m_declarativeDataReady = false;
++        m_qmlDataReady = false;
      }
  }
  
  void QmlProfilerApplication::v8Complete()
  {
      m_v8DataReady = true;
-     if (m_declarativeProfilerClient.state() != QQmlDebugClient::Enabled ||
 -    if (m_declarativeProfilerClient.state() != QDeclarativeDebugClient::Enabled ||
--            m_declarativeDataReady) {
++    if (m_qmlProfilerClient.state() != QQmlDebugClient::Enabled ||
++            m_qmlDataReady) {
          m_profileData.complete();
          // once complete is sent, reset the flag
          m_v8DataReady = false;
@@@ -80,7 -80,7 +80,7 @@@ private slots
      void logError(const QString &error);
      void logStatus(const QString &status);
  
--    void declarativeComplete();
++    void qmlComplete();
      void v8Complete();
  
  private:
      bool m_verbose;
      bool m_quitAfterSave;
  
 -    QDeclarativeDebugConnection m_connection;
 -    DeclarativeProfileClient m_declarativeProfilerClient;
 +    QQmlDebugConnection m_connection;
-     DeclarativeProfileClient m_declarativeProfilerClient;
++    QmlProfileClient m_qmlProfilerClient;
      V8ProfileClient m_v8profilerClient;
      ProfileData m_profileData;
      QTimer m_connectTimer;
      uint m_connectionAttempts;
  
--    bool m_declarativeDataReady;
++    bool m_qmlDataReady;
      bool m_v8DataReady;
  };