summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/animation/animatedtiles/animatedtiles.pro2
-rw-r--r--examples/animation/animatedtiles/animatedtiles.qrc11
-rw-r--r--examples/animation/animatedtiles/images/Time-For-Lunch-2.jpgbin0 -> 32471 bytes
-rw-r--r--examples/animation/animatedtiles/images/centered.pngbin0 -> 892 bytes
-rw-r--r--examples/animation/animatedtiles/images/ellipse.pngbin0 -> 10767 bytes
-rw-r--r--examples/animation/animatedtiles/images/figure8.pngbin0 -> 14050 bytes
-rw-r--r--examples/animation/animatedtiles/images/kinetic.pngbin0 -> 6776 bytes
-rw-r--r--examples/animation/animatedtiles/images/random.pngbin0 -> 14969 bytes
-rw-r--r--examples/animation/animatedtiles/images/tile.pngbin0 -> 16337 bytes
-rw-r--r--examples/animation/animatedtiles/main.cpp242
-rw-r--r--examples/animation/animation.pro21
-rw-r--r--examples/animation/appchooser/accessories-dictionary.pngbin0 -> 5396 bytes
-rw-r--r--examples/animation/appchooser/akregator.pngbin0 -> 4873 bytes
-rw-r--r--examples/animation/appchooser/appchooser.pro9
-rw-r--r--examples/animation/appchooser/appchooser.qrc8
-rw-r--r--examples/animation/appchooser/digikam.pngbin0 -> 3334 bytes
-rw-r--r--examples/animation/appchooser/k3b.pngbin0 -> 8220 bytes
-rw-r--r--examples/animation/appchooser/main.cpp124
-rw-r--r--examples/animation/easing/animation.h75
-rw-r--r--examples/animation/easing/easing.pro16
-rw-r--r--examples/animation/easing/form.ui201
-rw-r--r--examples/animation/easing/images/qt-logo.pngbin0 -> 5149 bytes
-rw-r--r--examples/animation/easing/main.cpp22
-rw-r--r--examples/animation/easing/resources.qrc5
-rw-r--r--examples/animation/easing/window.cpp133
-rw-r--r--examples/animation/easing/window.h49
-rw-r--r--examples/animation/example/example.pro12
-rw-r--r--examples/animation/example/main.cpp23
-rw-r--r--examples/animation/example/mainwindow.cpp220
-rw-r--r--examples/animation/example/mainwindow.h45
-rw-r--r--examples/animation/moveblocks/main.cpp274
-rw-r--r--examples/animation/moveblocks/moveblocks.pro8
-rw-r--r--examples/animation/padnavigator-ng/backside.ui208
-rw-r--r--examples/animation/padnavigator-ng/images/artsfftscope.pngbin0 -> 1294 bytes
-rw-r--r--examples/animation/padnavigator-ng/images/blue_angle_swirl.jpgbin0 -> 11826 bytes
-rw-r--r--examples/animation/padnavigator-ng/images/kontact_contacts.pngbin0 -> 4382 bytes
-rw-r--r--examples/animation/padnavigator-ng/images/kontact_journal.pngbin0 -> 3261 bytes
-rw-r--r--examples/animation/padnavigator-ng/images/kontact_mail.pngbin0 -> 3202 bytes
-rw-r--r--examples/animation/padnavigator-ng/images/kontact_notes.pngbin0 -> 3893 bytes
-rw-r--r--examples/animation/padnavigator-ng/images/kopeteavailable.pngbin0 -> 2380 bytes
-rw-r--r--examples/animation/padnavigator-ng/images/metacontact_online.pngbin0 -> 2545 bytes
-rw-r--r--examples/animation/padnavigator-ng/images/minitools.pngbin0 -> 2087 bytes
-rw-r--r--examples/animation/padnavigator-ng/main.cpp24
-rw-r--r--examples/animation/padnavigator-ng/padnavigator.pro24
-rw-r--r--examples/animation/padnavigator-ng/padnavigator.qrc14
-rw-r--r--examples/animation/padnavigator-ng/panel.cpp216
-rw-r--r--examples/animation/padnavigator-ng/panel.h59
-rw-r--r--examples/animation/padnavigator-ng/roundrectitem.cpp106
-rw-r--r--examples/animation/padnavigator-ng/roundrectitem.h47
-rw-r--r--examples/animation/padnavigator-ng/splashitem.cpp55
-rw-r--r--examples/animation/padnavigator-ng/splashitem.h31
-rw-r--r--examples/animation/photobrowser/main.cpp52
-rw-r--r--examples/animation/photobrowser/menu.cpp125
-rw-r--r--examples/animation/photobrowser/menu.h50
-rw-r--r--examples/animation/photobrowser/photobrowser.pro17
-rw-r--r--examples/animation/photobrowser/river.cpp561
-rw-r--r--examples/animation/photobrowser/river.h81
-rw-r--r--examples/animation/photobrowser/riveritem.cpp95
-rw-r--r--examples/animation/photobrowser/riveritem.h36
-rw-r--r--examples/animation/piemenu/main.cpp26
-rw-r--r--examples/animation/piemenu/piemenu.pro8
-rw-r--r--examples/animation/piemenu/qgraphicspiemenu.cpp220
-rw-r--r--examples/animation/piemenu/qgraphicspiemenu.h74
-rw-r--r--examples/animation/piemenu/qgraphicspiemenu_p.h48
-rw-r--r--examples/animation/piemenu/qgraphicspiemenusection_p.h58
-rw-r--r--examples/animation/piemenu/scene.cpp43
-rw-r--r--examples/animation/piemenu/scene.h30
-rw-r--r--examples/animation/research/memberfunctions/main.cpp48
-rw-r--r--examples/animation/research/memberfunctions/memberfunctions.pro16
-rw-r--r--examples/animation/research/memberfunctions/qvalueanimation.cpp73
-rw-r--r--examples/animation/research/memberfunctions/qvalueanimation.h89
-rw-r--r--examples/animation/research/memberfunctions/qvalueanimation_p.h47
-rw-r--r--examples/animation/research/propertytransform/main.cpp47
-rw-r--r--examples/animation/research/propertytransform/propertytransform.pro14
-rw-r--r--examples/animation/research/propertytransform/qpropertytransform.h78
-rw-r--r--examples/animation/research/sound/main.cpp74
-rw-r--r--examples/animation/research/sound/media/sax.mp3bin0 -> 417844 bytes
-rw-r--r--examples/animation/research/sound/sound.pro14
-rw-r--r--examples/animation/research/sound/sound.qrc5
-rw-r--r--examples/animation/states/accessories-dictionary.pngbin0 -> 5396 bytes
-rw-r--r--examples/animation/states/akregator.pngbin0 -> 4873 bytes
-rw-r--r--examples/animation/states/digikam.pngbin0 -> 3334 bytes
-rw-r--r--examples/animation/states/help-browser.pngbin0 -> 6984 bytes
-rw-r--r--examples/animation/states/k3b.pngbin0 -> 8220 bytes
-rw-r--r--examples/animation/states/kchart.pngbin0 -> 4887 bytes
-rw-r--r--examples/animation/states/main.cpp259
-rw-r--r--examples/animation/states/states.pro8
-rw-r--r--examples/animation/states/states.qrc10
-rw-r--r--examples/animation/stickman/animation.cpp152
-rw-r--r--examples/animation/stickman/animation.h40
-rw-r--r--examples/animation/stickman/animations/chillingbin0 -> 6508 bytes
-rw-r--r--examples/animation/stickman/animations/dancingbin0 -> 2348 bytes
-rw-r--r--examples/animation/stickman/animations/deadbin0 -> 268 bytes
-rw-r--r--examples/animation/stickman/animations/jumpingbin0 -> 1308 bytes
-rw-r--r--examples/animation/stickman/graphicsview.cpp15
-rw-r--r--examples/animation/stickman/graphicsview.h19
-rw-r--r--examples/animation/stickman/lifecycle.cpp176
-rw-r--r--examples/animation/stickman/lifecycle.h40
-rw-r--r--examples/animation/stickman/main.cpp58
-rw-r--r--examples/animation/stickman/node.cpp42
-rw-r--r--examples/animation/stickman/node.h26
-rw-r--r--examples/animation/stickman/stickman.cpp299
-rw-r--r--examples/animation/stickman/stickman.h59
-rw-r--r--examples/animation/stickman/stickman.pro12
-rw-r--r--examples/animation/sub-attaq/animationmanager.cpp97
-rw-r--r--examples/animation/sub-attaq/animationmanager.h68
-rw-r--r--examples/animation/sub-attaq/boat.cpp293
-rw-r--r--examples/animation/sub-attaq/boat.h100
-rw-r--r--examples/animation/sub-attaq/boat_p.h258
-rw-r--r--examples/animation/sub-attaq/bomb.cpp132
-rw-r--r--examples/animation/sub-attaq/bomb.h81
-rw-r--r--examples/animation/sub-attaq/custompropertyanimation.cpp114
-rw-r--r--examples/animation/sub-attaq/custompropertyanimation.h117
-rw-r--r--examples/animation/sub-attaq/custompropertyanimation_p.h64
-rw-r--r--examples/animation/sub-attaq/data.xml15
-rw-r--r--examples/animation/sub-attaq/graphicsscene.cpp368
-rw-r--r--examples/animation/sub-attaq/graphicsscene.h129
-rw-r--r--examples/animation/sub-attaq/main.cpp57
-rw-r--r--examples/animation/sub-attaq/mainwindow.cpp92
-rw-r--r--examples/animation/sub-attaq/mainwindow.h63
-rw-r--r--examples/animation/sub-attaq/pics/big/background.pngbin0 -> 48858 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/boat.pngbin0 -> 5198 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/bomb.pngbin0 -> 760 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/explosion/boat/step1.pngbin0 -> 5760 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/explosion/boat/step2.pngbin0 -> 9976 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/explosion/boat/step3.pngbin0 -> 12411 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/explosion/boat/step4.pngbin0 -> 15438 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/explosion/submarine/step1.pngbin0 -> 3354 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/explosion/submarine/step2.pngbin0 -> 6205 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/explosion/submarine/step3.pngbin0 -> 6678 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/explosion/submarine/step4.pngbin0 -> 6666 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/submarine.pngbin0 -> 3202 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/surface.pngbin0 -> 575 bytes
-rw-r--r--examples/animation/sub-attaq/pics/big/torpedo.pngbin0 -> 951 bytes
-rw-r--r--examples/animation/sub-attaq/pics/scalable/background-n810.svg171
-rw-r--r--examples/animation/sub-attaq/pics/scalable/background.svg171
-rw-r--r--examples/animation/sub-attaq/pics/scalable/boat.svg279
-rw-r--r--examples/animation/sub-attaq/pics/scalable/bomb.svg138
-rw-r--r--examples/animation/sub-attaq/pics/scalable/sand.svg103
-rw-r--r--examples/animation/sub-attaq/pics/scalable/see.svg44
-rw-r--r--examples/animation/sub-attaq/pics/scalable/sky.svg45
-rw-r--r--examples/animation/sub-attaq/pics/scalable/sub-attaq.svg1473
-rw-r--r--examples/animation/sub-attaq/pics/scalable/submarine.svg214
-rw-r--r--examples/animation/sub-attaq/pics/scalable/surface.svg49
-rw-r--r--examples/animation/sub-attaq/pics/scalable/torpedo.svg127
-rw-r--r--examples/animation/sub-attaq/pics/small/background.pngbin0 -> 34634 bytes
-rw-r--r--examples/animation/sub-attaq/pics/small/boat.pngbin0 -> 2394 bytes
-rw-r--r--examples/animation/sub-attaq/pics/small/bomb.pngbin0 -> 760 bytes
-rw-r--r--examples/animation/sub-attaq/pics/small/submarine.pngbin0 -> 1338 bytes
-rw-r--r--examples/animation/sub-attaq/pics/small/surface.pngbin0 -> 502 bytes
-rw-r--r--examples/animation/sub-attaq/pics/small/torpedo.pngbin0 -> 951 bytes
-rw-r--r--examples/animation/sub-attaq/pics/welcome/logo-a.pngbin0 -> 5972 bytes
-rw-r--r--examples/animation/sub-attaq/pics/welcome/logo-a2.pngbin0 -> 5969 bytes
-rw-r--r--examples/animation/sub-attaq/pics/welcome/logo-b.pngbin0 -> 6869 bytes
-rw-r--r--examples/animation/sub-attaq/pics/welcome/logo-dash.pngbin0 -> 2255 bytes
-rw-r--r--examples/animation/sub-attaq/pics/welcome/logo-excl.pngbin0 -> 2740 bytes
-rw-r--r--examples/animation/sub-attaq/pics/welcome/logo-q.pngbin0 -> 7016 bytes
-rw-r--r--examples/animation/sub-attaq/pics/welcome/logo-s.pngbin0 -> 5817 bytes
-rw-r--r--examples/animation/sub-attaq/pics/welcome/logo-t.pngbin0 -> 3717 bytes
-rw-r--r--examples/animation/sub-attaq/pics/welcome/logo-t2.pngbin0 -> 3688 bytes
-rw-r--r--examples/animation/sub-attaq/pics/welcome/logo-u.pngbin0 -> 5374 bytes
-rw-r--r--examples/animation/sub-attaq/pixmapitem.cpp59
-rw-r--r--examples/animation/sub-attaq/pixmapitem.h63
-rw-r--r--examples/animation/sub-attaq/states.cpp289
-rw-r--r--examples/animation/sub-attaq/states.h158
-rw-r--r--examples/animation/sub-attaq/sub-attaq.pro36
-rw-r--r--examples/animation/sub-attaq/subattaq.qrc38
-rw-r--r--examples/animation/sub-attaq/submarine.cpp219
-rw-r--r--examples/animation/sub-attaq/submarine.h97
-rw-r--r--examples/animation/sub-attaq/submarine_p.h136
-rw-r--r--examples/animation/sub-attaq/torpedo.cpp126
-rw-r--r--examples/animation/sub-attaq/torpedo.h81
-rw-r--r--examples/declarative/animation/animation.qml28
-rw-r--r--examples/declarative/behaviours/MyRect.qml4
-rw-r--r--examples/declarative/behaviours/test.qml37
-rw-r--r--examples/declarative/connections/connections.qml9
-rw-r--r--examples/declarative/contacts/contacts.pro22
-rw-r--r--examples/declarative/contacts/contacts.qml44
-rw-r--r--examples/declarative/contacts/dummydata/contactModel.qml103
-rw-r--r--examples/declarative/contacts/main.cpp80
-rw-r--r--examples/declarative/declarative.pro4
-rw-r--r--examples/declarative/dial/DialLibrary/Dial.qml13
-rw-r--r--examples/declarative/dial/DialLibrary/background.svg385
-rw-r--r--examples/declarative/dial/DialLibrary/needle.svg26
-rw-r--r--examples/declarative/dial/DialLibrary/needle_shadow.svg30
-rw-r--r--examples/declarative/dial/DialLibrary/overlay.svg47
-rw-r--r--examples/declarative/dial/dial.qml14
-rw-r--r--examples/declarative/easing/easing.qml67
-rw-r--r--examples/declarative/follow/follow.qml35
-rw-r--r--examples/declarative/follow/pong.qml55
-rw-r--r--examples/declarative/listview/content/MediaButton.qml21
-rw-r--r--examples/declarative/listview/content/pics/button-pressed.pngbin0 -> 571 bytes
-rw-r--r--examples/declarative/listview/content/pics/button.pngbin0 -> 564 bytes
-rw-r--r--examples/declarative/listview/content/pics/fruit-salad.jpgbin0 -> 17952 bytes
-rw-r--r--examples/declarative/listview/content/pics/hamburger.jpgbin0 -> 8572 bytes
-rw-r--r--examples/declarative/listview/content/pics/lemonade.jpgbin0 -> 6645 bytes
-rw-r--r--examples/declarative/listview/content/pics/pancakes.jpgbin0 -> 9163 bytes
-rw-r--r--examples/declarative/listview/content/pics/vegetable-soup.jpgbin0 -> 8639 bytes
-rw-r--r--examples/declarative/listview/dummydata/MyPetsModel.qml51
-rw-r--r--examples/declarative/listview/dummydata/Recipies.qml112
-rw-r--r--examples/declarative/listview/highlight.qml56
-rw-r--r--examples/declarative/listview/listview.qml81
-rw-r--r--examples/declarative/listview/recipes.qml83
-rw-r--r--examples/declarative/minehunt/Description.qml10
-rw-r--r--examples/declarative/minehunt/Explosion.qml6
-rw-r--r--examples/declarative/minehunt/main.cpp312
-rw-r--r--examples/declarative/minehunt/minehunt.pro8
-rw-r--r--examples/declarative/minehunt/minehunt.qml73
-rw-r--r--examples/declarative/minehunt/pics/No-Ones-Laughing-3.jpgbin0 -> 30730 bytes
-rw-r--r--examples/declarative/minehunt/pics/bomb-color.pngbin0 -> 284 bytes
-rw-r--r--examples/declarative/minehunt/pics/bomb.pngbin0 -> 535 bytes
-rw-r--r--examples/declarative/minehunt/pics/cachepix-black.pngbin0 -> 1658 bytes
-rw-r--r--examples/declarative/minehunt/pics/cachepix-black.sci5
-rw-r--r--examples/declarative/minehunt/pics/cachepix-boxless.pngbin0 -> 1819 bytes
-rw-r--r--examples/declarative/minehunt/pics/cachepix-boxless.sci5
-rw-r--r--examples/declarative/minehunt/pics/flag-color.pngbin0 -> 219 bytes
-rw-r--r--examples/declarative/minehunt/pics/flag.pngbin0 -> 196 bytes
-rw-r--r--examples/declarative/minehunt/pics/frown.pngbin0 -> 1036 bytes
-rw-r--r--examples/declarative/minehunt/pics/glee.pngbin0 -> 1082 bytes
-rw-r--r--examples/declarative/minehunt/pics/smile.pngbin0 -> 1028 bytes
-rw-r--r--examples/declarative/minehunt/pics/star.pngbin0 -> 2677 bytes
-rw-r--r--examples/declarative/mouseregion/mouse.qml24
-rw-r--r--examples/declarative/namespaces/BlueStuff/Rect.qml1
-rw-r--r--examples/declarative/namespaces/Local.qml1
-rw-r--r--examples/declarative/namespaces/components.qml17
-rw-r--r--examples/declarative/namespaces/lib/Chronos/Clock.qml15
-rw-r--r--examples/declarative/namespaces/lib/Chronos/Hand.qml9
-rw-r--r--examples/declarative/namespaces/lib/Chronos/pics/clockface.pngbin0 -> 46895 bytes
-rw-r--r--examples/declarative/namespaces/lib/Path/PathLabel.qml1
-rw-r--r--examples/declarative/namespaces/lib/RedStuff/Rect.qml1
-rw-r--r--examples/declarative/namespaces/lib/Wrong/Wrong.qml3
-rw-r--r--examples/declarative/namespaces/library.qml12
-rw-r--r--examples/declarative/namespaces/path.qml18
-rw-r--r--examples/declarative/namespaces/simple.qml5
-rw-r--r--examples/declarative/namespaces/wrong1.qml4
-rw-r--r--examples/declarative/scrollbar/ScrollBar.qml26
-rw-r--r--examples/declarative/scrollbar/display.qml28
-rw-r--r--examples/declarative/scrollbar/pics/niagara_falls.jpgbin0 -> 604121 bytes
-rw-r--r--examples/declarative/slideswitch/Switch.qml52
-rw-r--r--examples/declarative/slideswitch/background.svg23
-rw-r--r--examples/declarative/slideswitch/display.qml3
-rw-r--r--examples/declarative/slideswitch/knob.svg867
-rw-r--r--examples/declarative/states/states.qml40
-rw-r--r--examples/declarative/states/transitions.qml68
-rw-r--r--examples/declarative/support/contact.cpp83
-rw-r--r--examples/declarative/support/contact.h141
-rw-r--r--examples/declarative/support/contactmodel.cpp159
-rw-r--r--examples/declarative/support/contactmodel.h55
-rw-r--r--examples/declarative/support/support.pro12
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_an_animation.qml22
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton1.qml4
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton2.qml10
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton3.qml23
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton4.qml65
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton5.qml70
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml34
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/Contact3.qml27
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/Contact4.qml27
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/ContactField1.qml17
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/ContactField2.qml19
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/ContactField3.qml35
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/ContactField4.qml35
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/FieldText3.qml93
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/FieldText4.qml98
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/RemoveButton1.qml70
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/RemoveButton2.qml76
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/RemoveButton3.qml76
-rw-r--r--examples/declarative/tutorials/contacts/2_Reuse/RemoveButton4.qml80
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml8
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/Button.qml38
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/Contact.qml28
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/ContactField.qml35
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/ContactView1.qml22
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/ContactView2.qml62
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/ContactView3.qml67
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/FieldText.qml98
-rw-r--r--examples/declarative/tutorials/contacts/3_Collections/RemoveButton.qml80
-rw-r--r--examples/declarative/tutorials/contacts/shared/contacts.sqlitebin0 -> 12288 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/cancel.pngbin0 -> 1038 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/email.pngbin0 -> 977 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/new.pngbin0 -> 688 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/ok.pngbin0 -> 655 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/phone.pngbin0 -> 624 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/search.pngbin0 -> 635 bytes
-rw-r--r--examples/declarative/tutorials/contacts/shared/pics/trash.pngbin0 -> 989 bytes
-rw-r--r--examples/declarative/tutorials/contacts/t8/Button.qml33
-rw-r--r--examples/declarative/tutorials/contacts/t8/Contact.qml80
-rw-r--r--examples/declarative/tutorials/contacts/t8/Field.qml54
-rw-r--r--examples/declarative/tutorials/contacts/t8/FieldRemover.qml57
-rw-r--r--examples/declarative/tutorials/contacts/t8/FieldText.qml89
-rw-r--r--examples/declarative/tutorials/contacts/t8/SearchBar.qml16
-rw-r--r--examples/declarative/tutorials/contacts/t8/contacts.qml133
-rw-r--r--examples/declarative/tutorials/t1/tutorial1.qml3
-rw-r--r--examples/declarative/tutorials/t2/Cell.qml7
-rw-r--r--examples/declarative/tutorials/t2/tutorial2.qml11
-rw-r--r--examples/declarative/tutorials/t3/Cell.qml7
-rw-r--r--examples/declarative/tutorials/t3/tutorial3.qml27
-rw-r--r--examples/declarative/velocity/Day.qml41
-rw-r--r--examples/declarative/velocity/cork.jpgbin0 -> 88766 bytes
-rw-r--r--examples/declarative/velocity/sticky.pngbin0 -> 15319 bytes
-rw-r--r--examples/declarative/velocity/tack.pngbin0 -> 7282 bytes
-rw-r--r--examples/declarative/velocity/velocity.qml81
-rw-r--r--examples/declarative/webview/autosize.qml42
-rw-r--r--examples/declarative/webview/content/SpinSquare.qml12
-rw-r--r--examples/declarative/webview/inline-html.qml13
-rw-r--r--examples/declarative/webview/inline-xhtml.qml14
-rw-r--r--examples/declarative/webview/qml-in-html.qml20
-rw-r--r--examples/declarative/webview/transparent.qml6
-rw-r--r--examples/declarative/xmldata/daringfireball.qml25
-rw-r--r--examples/declarative/xmldata/yahoonews.qml38
-rw-r--r--examples/examples.pro3
-rw-r--r--examples/opengl/hellogl_es2/glwidget.cpp391
-rw-r--r--examples/opengl/hellogl_es2/glwidget.h31
-rw-r--r--examples/statemachine/README36
-rw-r--r--examples/statemachine/citizenquartz/citizenquartz.pro20
-rw-r--r--examples/statemachine/citizenquartz/citizenquartz.qrc5
-rw-r--r--examples/statemachine/citizenquartz/clock.cpp382
-rw-r--r--examples/statemachine/citizenquartz/clock.h60
-rw-r--r--examples/statemachine/citizenquartz/clockbutton.cpp39
-rw-r--r--examples/statemachine/citizenquartz/clockbutton.h25
-rw-r--r--examples/statemachine/citizenquartz/clockdisplay.cpp140
-rw-r--r--examples/statemachine/citizenquartz/clockdisplay.h75
-rw-r--r--examples/statemachine/citizenquartz/images/alarm.pngbin0 -> 434 bytes
-rw-r--r--examples/statemachine/citizenquartz/main.cpp23
-rw-r--r--examples/statemachine/citizenquartz/propertyaddstate.cpp46
-rw-r--r--examples/statemachine/citizenquartz/propertyaddstate.h33
-rw-r--r--examples/statemachine/citizenquartz/sound/alarm.wavbin0 -> 3238264 bytes
-rw-r--r--examples/statemachine/citizenquartz/timeperiod.h84
-rw-r--r--examples/statemachine/clockticking/clockticking.pro10
-rw-r--r--examples/statemachine/clockticking/main.cpp101
-rw-r--r--examples/statemachine/composition/composition.pro7
-rw-r--r--examples/statemachine/composition/main.cpp74
-rw-r--r--examples/statemachine/eventtransitions/eventtransitions.pro7
-rw-r--r--examples/statemachine/eventtransitions/main.cpp72
-rw-r--r--examples/statemachine/factorial/factorial.pro10
-rw-r--r--examples/statemachine/factorial/main.cpp140
-rw-r--r--examples/statemachine/helloworld/helloworld.pro10
-rw-r--r--examples/statemachine/helloworld/main.cpp48
-rw-r--r--examples/statemachine/pauseandresume/main.cpp72
-rw-r--r--examples/statemachine/pauseandresume/pauseandresume.pro7
-rw-r--r--examples/statemachine/pingpong/main.cpp112
-rw-r--r--examples/statemachine/pingpong/pingpong.pro10
-rw-r--r--examples/statemachine/statemachine.pro17
-rw-r--r--examples/statemachine/trafficlight/main.cpp158
-rw-r--r--examples/statemachine/trafficlight/trafficlight.pro12
-rw-r--r--examples/statemachine/twowaybutton/main.cpp48
-rw-r--r--examples/statemachine/twowaybutton/twowaybutton.pro7
347 files changed, 19326 insertions, 303 deletions
diff --git a/examples/animation/animatedtiles/animatedtiles.pro b/examples/animation/animatedtiles/animatedtiles.pro
new file mode 100644
index 0000000..9e9062c
--- /dev/null
+++ b/examples/animation/animatedtiles/animatedtiles.pro
@@ -0,0 +1,2 @@
+SOURCES += main.cpp
+RESOURCES += animatedtiles.qrc
diff --git a/examples/animation/animatedtiles/animatedtiles.qrc b/examples/animation/animatedtiles/animatedtiles.qrc
new file mode 100644
index 0000000..c43a979
--- /dev/null
+++ b/examples/animation/animatedtiles/animatedtiles.qrc
@@ -0,0 +1,11 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>images/Time-For-Lunch-2.jpg</file>
+ <file>images/centered.png</file>
+ <file>images/ellipse.png</file>
+ <file>images/figure8.png</file>
+ <file>images/kinetic.png</file>
+ <file>images/random.png</file>
+ <file>images/tile.png</file>
+</qresource>
+</RCC>
diff --git a/examples/animation/animatedtiles/images/Time-For-Lunch-2.jpg b/examples/animation/animatedtiles/images/Time-For-Lunch-2.jpg
new file mode 100644
index 0000000..c57a555
--- /dev/null
+++ b/examples/animation/animatedtiles/images/Time-For-Lunch-2.jpg
Binary files differ
diff --git a/examples/animation/animatedtiles/images/centered.png b/examples/animation/animatedtiles/images/centered.png
new file mode 100644
index 0000000..e416156
--- /dev/null
+++ b/examples/animation/animatedtiles/images/centered.png
Binary files differ
diff --git a/examples/animation/animatedtiles/images/ellipse.png b/examples/animation/animatedtiles/images/ellipse.png
new file mode 100644
index 0000000..2c3ba88
--- /dev/null
+++ b/examples/animation/animatedtiles/images/ellipse.png
Binary files differ
diff --git a/examples/animation/animatedtiles/images/figure8.png b/examples/animation/animatedtiles/images/figure8.png
new file mode 100644
index 0000000..6b05804
--- /dev/null
+++ b/examples/animation/animatedtiles/images/figure8.png
Binary files differ
diff --git a/examples/animation/animatedtiles/images/kinetic.png b/examples/animation/animatedtiles/images/kinetic.png
new file mode 100644
index 0000000..55cfa55
--- /dev/null
+++ b/examples/animation/animatedtiles/images/kinetic.png
Binary files differ
diff --git a/examples/animation/animatedtiles/images/random.png b/examples/animation/animatedtiles/images/random.png
new file mode 100644
index 0000000..415d96f
--- /dev/null
+++ b/examples/animation/animatedtiles/images/random.png
Binary files differ
diff --git a/examples/animation/animatedtiles/images/tile.png b/examples/animation/animatedtiles/images/tile.png
new file mode 100644
index 0000000..c8f39d8
--- /dev/null
+++ b/examples/animation/animatedtiles/images/tile.png
Binary files differ
diff --git a/examples/animation/animatedtiles/main.cpp b/examples/animation/animatedtiles/main.cpp
new file mode 100644
index 0000000..e4a774c
--- /dev/null
+++ b/examples/animation/animatedtiles/main.cpp
@@ -0,0 +1,242 @@
+#include <QtGui>
+#ifdef QT_EXPERIMENTAL_SOLUTION
+# include "qgraphicswidget.h"
+# include "qstate.h"
+# include "qstatemachine.h"
+# include "qgraphicswidget.h"
+# include "qparallelanimationgroup.h"
+# include "qpropertyanimation.h"
+#else
+#include <QtCore/qstate.h>
+#endif
+
+class Pixmap : public QObject, public QGraphicsPixmapItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QPointF pos READ pos WRITE setPos)
+public:
+ Pixmap(const QPixmap &pix)
+ : QObject(), QGraphicsPixmapItem(pix)
+ {
+ setCacheMode(DeviceCoordinateCache);
+ }
+};
+
+class Button : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ Button(const QPixmap &pixmap, QGraphicsItem *parent = 0)
+ : QGraphicsWidget(parent), _pix(pixmap)
+ {
+ setAcceptHoverEvents(true);
+ setCacheMode(DeviceCoordinateCache);
+ }
+
+ QRectF boundingRect() const
+ {
+ return QRectF(-65, -65, 130, 130);
+ }
+
+ QPainterPath shape() const
+ {
+ QPainterPath path;
+ path.addEllipse(boundingRect());
+ return path;
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
+ {
+ bool down = option->state & QStyle::State_Sunken;
+ QRectF r = boundingRect();
+ QLinearGradient grad(r.topLeft(), r.bottomRight());
+ grad.setColorAt(down ? 1 : 0, option->state & QStyle::State_MouseOver ? Qt::white : Qt::lightGray);
+ grad.setColorAt(down ? 0 : 1, Qt::darkGray);
+ painter->setPen(Qt::darkGray);
+ painter->setBrush(grad);
+ painter->drawEllipse(r);
+ QLinearGradient grad2(r.topLeft(), r.bottomRight());
+ grad.setColorAt(down ? 1 : 0, Qt::darkGray);
+ grad.setColorAt(down ? 0 : 1, Qt::lightGray);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(grad);
+ if (down)
+ painter->translate(2, 2);
+ painter->drawEllipse(r.adjusted(5, 5, -5, -5));
+ painter->drawPixmap(-_pix.width()/2, -_pix.height()/2, _pix);
+ }
+
+signals:
+ void pressed();
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *)
+ {
+ emit pressed();
+ update();
+ }
+
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+ {
+ update();
+ }
+
+private:
+ QPixmap _pix;
+};
+
+class View : public QGraphicsView
+{
+public:
+ View(QGraphicsScene *scene) : QGraphicsView(scene) { }
+
+protected:
+ void resizeEvent(QResizeEvent *event)
+ {
+ QGraphicsView::resizeEvent(event);
+ fitInView(sceneRect(), Qt::KeepAspectRatio);
+ }
+};
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QPixmap kineticPix(":/images/kinetic.png");
+ QPixmap bgPix(":/images/Time-For-Lunch-2.jpg");
+
+ QGraphicsScene scene(-350, -350, 700, 700);
+
+ QList<Pixmap *> items;
+ for (int i = 0; i < 64; ++i) {
+ Pixmap *item = new Pixmap(kineticPix);
+ item->setOffset(-kineticPix.width()/2, -kineticPix.height()/2);
+ item->setZValue(i);
+ items << item;
+ scene.addItem(item);
+ }
+
+ // Buttons
+ QGraphicsItem *buttonParent = new QGraphicsRectItem;
+ Button *ellipseButton = new Button(QPixmap(":/images/ellipse.png"), buttonParent);
+ Button *figure8Button = new Button(QPixmap(":/images/figure8.png"), buttonParent);
+ Button *randomButton = new Button(QPixmap(":/images/random.png"), buttonParent);
+ Button *tiledButton = new Button(QPixmap(":/images/tile.png"), buttonParent);
+ Button *centeredButton = new Button(QPixmap(":/images/centered.png"), buttonParent);
+
+ ellipseButton->setPos(-100, -100);
+ figure8Button->setPos(100, -100);
+ randomButton->setPos(0, 0);
+ tiledButton->setPos(-100, 100);
+ centeredButton->setPos(100, 100);
+
+ scene.addItem(buttonParent);
+ buttonParent->scale(0.75, 0.75);
+ buttonParent->setPos(200, 200);
+ buttonParent->setZValue(65);
+
+ // States
+ QState *rootState = new QState;
+ QState *ellipseState = new QState(rootState);
+ QState *figure8State = new QState(rootState);
+ QState *randomState = new QState(rootState);
+ QState *tiledState = new QState(rootState);
+ QState *centeredState = new QState(rootState);
+
+ // Values
+ for (int i = 0; i < 64; ++i) {
+ Pixmap *item = items.at(i);
+ // Ellipse
+ ellipseState->setPropertyOnEntry(item, "pos",
+ QPointF(cos((i / 63.0) * 6.28) * 250,
+ sin((i / 63.0) * 6.28) * 250));
+
+ // Figure 8
+ figure8State->setPropertyOnEntry(item, "pos",
+ QPointF(sin((i / 63.0) * 6.28) * 250,
+ sin(((i * 2)/63.0) * 6.28) * 250));
+
+ // Random
+ randomState->setPropertyOnEntry(item, "pos",
+ QPointF(-250 + qrand() % 500,
+ -250 + qrand() % 500));
+
+ // Tiled
+ tiledState->setPropertyOnEntry(item, "pos",
+ QPointF(((i % 8) - 4) * kineticPix.width() + kineticPix.width() / 2,
+ ((i / 8) - 4) * kineticPix.height() + kineticPix.height() / 2));
+
+ // Centered
+ centeredState->setPropertyOnEntry(item, "pos", QPointF());
+ }
+
+ // Ui
+ View *view = new View(&scene);
+ view->setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Animated Tiles"));
+ view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+ view->setBackgroundBrush(bgPix);
+ view->setCacheMode(QGraphicsView::CacheBackground);
+ view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
+ view->show();
+
+ QStateMachine states;
+ states.addState(rootState);
+ states.setInitialState(rootState);
+ rootState->setInitialState(centeredState);
+
+ // rootState->addTransition(ellipseButton, SIGNAL(pressed()), ellipseState);
+ QParallelAnimationGroup *group = new QParallelAnimationGroup;
+ for (int i = 0; i < 64; ++i) {
+ QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos");
+ anim->setDuration(750 + i * 25);
+ anim->setEasingCurve(QEasingCurve::InOutBack);
+ group->addAnimation(anim);
+ }
+ rootState->addAnimatedTransition(ellipseButton, SIGNAL(pressed()), ellipseState, group);
+
+ group = new QParallelAnimationGroup;
+ for (int i = 0; i < 64; ++i) {
+ QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos");
+ anim->setDuration(750 + i * 25);
+ anim->setEasingCurve(QEasingCurve::InOutBack);
+ group->addAnimation(anim);
+ }
+ rootState->addAnimatedTransition(figure8Button, SIGNAL(pressed()), figure8State, group);
+
+ group = new QParallelAnimationGroup;
+ for (int i = 0; i < 64; ++i) {
+ QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos");
+ anim->setDuration(750 + i * 25);
+ anim->setEasingCurve(QEasingCurve::InOutBack);
+ group->addAnimation(anim);
+ }
+ rootState->addAnimatedTransition(randomButton, SIGNAL(pressed()), randomState, group);
+
+ group = new QParallelAnimationGroup;
+ for (int i = 0; i < 64; ++i) {
+ QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos");
+ anim->setDuration(750 + i * 25);
+ anim->setEasingCurve(QEasingCurve::InOutBack);
+ group->addAnimation(anim);
+ }
+ rootState->addAnimatedTransition(tiledButton, SIGNAL(pressed()), tiledState, group);
+
+ group = new QParallelAnimationGroup;
+ for (int i = 0; i < 64; ++i) {
+ QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos");
+ anim->setDuration(750 + i * 25);
+ anim->setEasingCurve(QEasingCurve::InOutBack);
+ group->addAnimation(anim);
+ }
+ rootState->addAnimatedTransition(centeredButton, SIGNAL(pressed()), centeredState, group);
+
+ states.start();
+ QTimer timer;
+ timer.start(125);
+ timer.setSingleShot(true);
+ rootState->addAnimatedTransition(&timer, SIGNAL(timeout()), ellipseState, group);
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/examples/animation/animation.pro b/examples/animation/animation.pro
new file mode 100644
index 0000000..d5121a1
--- /dev/null
+++ b/examples/animation/animation.pro
@@ -0,0 +1,21 @@
+TEMPLATE = \
+ subdirs
+SUBDIRS += \
+ animatedtiles \
+ appchooser \
+ easing \
+ example \
+ moveblocks \
+ padnavigator-ng \
+ photobrowser \
+ piemenu \
+ selectbutton \
+ states \
+ stickman \
+ sub-attaq
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/animation
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS animation.pro README
+sources.path = $$[QT_INSTALL_EXAMPLES]/animation
+INSTALLS += target sources
diff --git a/examples/animation/appchooser/accessories-dictionary.png b/examples/animation/appchooser/accessories-dictionary.png
new file mode 100644
index 0000000..e9bd55d
--- /dev/null
+++ b/examples/animation/appchooser/accessories-dictionary.png
Binary files differ
diff --git a/examples/animation/appchooser/akregator.png b/examples/animation/appchooser/akregator.png
new file mode 100644
index 0000000..a086f45
--- /dev/null
+++ b/examples/animation/appchooser/akregator.png
Binary files differ
diff --git a/examples/animation/appchooser/appchooser.pro b/examples/animation/appchooser/appchooser.pro
new file mode 100644
index 0000000..8cda19a
--- /dev/null
+++ b/examples/animation/appchooser/appchooser.pro
@@ -0,0 +1,9 @@
+# Input
+SOURCES += main.cpp
+RESOURCES += appchooser.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/animation/appchooser
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS appchooser.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/animation/appchooser
+INSTALLS += target sources
diff --git a/examples/animation/appchooser/appchooser.qrc b/examples/animation/appchooser/appchooser.qrc
new file mode 100644
index 0000000..28a3e1c
--- /dev/null
+++ b/examples/animation/appchooser/appchooser.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>accessories-dictionary.png</file>
+ <file>akregator.png</file>
+ <file>digikam.png</file>
+ <file>k3b.png</file>
+</qresource>
+</RCC>
diff --git a/examples/animation/appchooser/digikam.png b/examples/animation/appchooser/digikam.png
new file mode 100644
index 0000000..9de9fb2
--- /dev/null
+++ b/examples/animation/appchooser/digikam.png
Binary files differ
diff --git a/examples/animation/appchooser/k3b.png b/examples/animation/appchooser/k3b.png
new file mode 100644
index 0000000..bbcafcf
--- /dev/null
+++ b/examples/animation/appchooser/k3b.png
Binary files differ
diff --git a/examples/animation/appchooser/main.cpp b/examples/animation/appchooser/main.cpp
new file mode 100644
index 0000000..536bbb6
--- /dev/null
+++ b/examples/animation/appchooser/main.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <QtGui>
+#ifdef QT_EXPERIMENTAL_SOLUTION
+#include "qtgraphicswidget.h"
+#endif
+
+
+class Pixmap : public QGraphicsWidget
+{
+ Q_OBJECT
+
+public:
+ Pixmap(const QPixmap &pix, QGraphicsItem *parent = 0)
+ : QGraphicsWidget(parent), orig(pix), p(pix)
+ {
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->drawPixmap(QPointF(), p);
+ }
+
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent * )
+ {
+ emit clicked();
+ }
+
+ virtual void setGeometry(const QRectF &rect)
+ {
+ QGraphicsWidget::setGeometry(rect);
+
+ if (rect.size().width() > orig.size().width())
+ p = orig.scaled(rect.size().toSize());
+ else
+ p = orig;
+ }
+
+Q_SIGNALS:
+ void clicked();
+
+private:
+ QPixmap orig;
+ QPixmap p;
+};
+
+void createStateAndTransition(QObject *o1, const QRect &selectedRect, QState *parent)
+{
+ QState *state = new QState(parent);
+ state->setPropertyOnEntry(o1, "geometry", selectedRect);
+
+ QPropertyAnimation *animation = new QPropertyAnimation(o1, "geometry");
+ parent->addAnimatedTransition(o1, SIGNAL(clicked()), state, animation);
+}
+
+int main(int argc, char **argv)
+{
+ Q_INIT_RESOURCE(appchooser);
+
+ QApplication app(argc, argv);
+
+ Pixmap *p1 = new Pixmap(QPixmap(":/digikam.png"));
+ Pixmap *p2 = new Pixmap(QPixmap(":/akregator.png"));
+ Pixmap *p3 = new Pixmap(QPixmap(":/accessories-dictionary.png"));
+ Pixmap *p4 = new Pixmap(QPixmap(":/k3b.png"));
+
+ p1->setObjectName("p1");
+ p2->setObjectName("p2");
+ p3->setObjectName("p3");
+ p4->setObjectName("p4");
+
+ p1->setGeometry(QRectF(0.0, 0.0, 64.0, 64.0));
+ p2->setGeometry(QRectF(236.0, 0.0, 64.0, 64.0));
+ p3->setGeometry(QRectF(236.0, 236.0, 64.0, 64.0));
+ p4->setGeometry(QRectF(0.0, 236.0, 64.0, 64.0));
+
+ QGraphicsScene scene(0, 0, 300, 300);
+ scene.setBackgroundBrush(Qt::white);
+ scene.addItem(p1);
+ scene.addItem(p2);
+ scene.addItem(p3);
+ scene.addItem(p4);
+
+ QGraphicsView window(&scene);
+ window.setFrameStyle(0);
+ window.setAlignment(Qt::AlignLeft | Qt::AlignTop);
+ window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(QState::RestoreProperties);
+
+ QState *group = new QState(machine.rootState());
+ group->setObjectName("group");
+ QRect selectedRect(86, 86, 128, 128);
+
+ QState *idleState = new QState(group);
+ group->setInitialState(idleState);
+
+ createStateAndTransition(p1, selectedRect, group);
+ createStateAndTransition(p2, selectedRect, group);
+ createStateAndTransition(p3, selectedRect, group);
+ createStateAndTransition(p4, selectedRect, group);
+
+ machine.setInitialState(group);
+ machine.start();
+
+ window.resize(300, 300);
+ window.show();
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/examples/animation/easing/animation.h b/examples/animation/easing/animation.h
new file mode 100644
index 0000000..db67810
--- /dev/null
+++ b/examples/animation/easing/animation.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ANIMATION_H
+#define ANIMATION_H
+
+#include <QtGui>
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qpropertyanimation.h"
+#else
+# include <QtCore/qpropertyanimation.h>
+#endif
+
+class Animation : public QPropertyAnimation {
+public:
+ enum PathType {
+ LinearPath,
+ CirclePath,
+ NPathTypes
+ };
+ Animation(QObject *target, const QByteArray &prop)
+ : QPropertyAnimation(target, prop)
+ {
+ setPathType(LinearPath);
+ }
+
+ void setPathType(PathType pathType)
+ {
+ if (pathType >= NPathTypes)
+ qWarning("Unknown pathType %d", pathType);
+
+ m_pathType = pathType;
+ m_path = QPainterPath();
+ }
+
+ void updateCurrentTime(int msecs)
+ {
+ if (m_pathType == CirclePath) {
+ if (m_path.isEmpty()) {
+ QPointF to = endValue().toPointF();
+ QPointF from = startValue().toPointF();
+ m_path.moveTo(from);
+ m_path.addEllipse(QRectF(from, to));
+ }
+ int dura = duration();
+ const qreal progress = ((dura == 0) ? 1 : ((((currentTime() - 1) % dura) + 1) / qreal(dura)));
+
+ qreal easedProgress = easingCurve().valueForProgress(progress);
+ if (easedProgress > 1.0) {
+ easedProgress -= 1.0;
+ } else if (easedProgress < 0) {
+ easedProgress += 1.0;
+ }
+ QPointF pt = m_path.pointAtPercent(easedProgress);
+ updateCurrentValue(pt);
+ emit valueChanged(pt);
+ } else {
+ QPropertyAnimation::updateCurrentTime(msecs);
+ }
+ }
+
+ QPainterPath m_path;
+ PathType m_pathType;
+};
+
+#endif // ANIMATION_H
diff --git a/examples/animation/easing/easing.pro b/examples/animation/easing/easing.pro
new file mode 100644
index 0000000..fa5b22d
--- /dev/null
+++ b/examples/animation/easing/easing.pro
@@ -0,0 +1,16 @@
+######################################################################
+# Automatically generated by qmake (2.01a) to 2. okt 23:22:11 2008
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+HEADERS += window.h animation.h
+SOURCES += main.cpp window.cpp
+
+FORMS += form.ui
+
+RESOURCES = resources.qrc
diff --git a/examples/animation/easing/form.ui b/examples/animation/easing/form.ui
new file mode 100644
index 0000000..b60ade8
--- /dev/null
+++ b/examples/animation/easing/form.ui
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>545</width>
+ <height>471</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Easing curves</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0" colspan="2">
+ <widget class="QListWidget" name="easingCurvePicker">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>120</height>
+ </size>
+ </property>
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="movement">
+ <enum>QListView::Static</enum>
+ </property>
+ <property name="isWrapping" stdset="0">
+ <bool>false</bool>
+ </property>
+ <property name="viewMode">
+ <enum>QListView::IconMode</enum>
+ </property>
+ <property name="selectionRectVisible">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Path type</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QRadioButton" name="lineRadio">
+ <property name="text">
+ <string>Line</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <attribute name="buttonGroup">
+ <string>buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="circleRadio">
+ <property name="text">
+ <string>Circle</string>
+ </property>
+ <attribute name="buttonGroup">
+ <string>buttonGroup</string>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Properties</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Period</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QDoubleSpinBox" name="periodSpinBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <double>-1.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.100000000000000</double>
+ </property>
+ <property name="value">
+ <double>-1.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Amplitude</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDoubleSpinBox" name="amplitudeSpinBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <double>-1.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.100000000000000</double>
+ </property>
+ <property name="value">
+ <double>-1.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Overshoot</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QDoubleSpinBox" name="overshootSpinBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <double>-1.000000000000000</double>
+ </property>
+ <property name="singleStep">
+ <double>0.100000000000000</double>
+ </property>
+ <property name="value">
+ <double>-1.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="1">
+ <widget class="QGraphicsView" name="graphicsView">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+ <buttongroups>
+ <buttongroup name="buttonGroup"/>
+ </buttongroups>
+</ui>
diff --git a/examples/animation/easing/images/qt-logo.png b/examples/animation/easing/images/qt-logo.png
new file mode 100644
index 0000000..14ddf2a
--- /dev/null
+++ b/examples/animation/easing/images/qt-logo.png
Binary files differ
diff --git a/examples/animation/easing/main.cpp b/examples/animation/easing/main.cpp
new file mode 100644
index 0000000..139f2da
--- /dev/null
+++ b/examples/animation/easing/main.cpp
@@ -0,0 +1,22 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include "window.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ Window w;
+ w.resize(400, 400);
+ w.show();
+ return app.exec();
+}
diff --git a/examples/animation/easing/resources.qrc b/examples/animation/easing/resources.qrc
new file mode 100644
index 0000000..7e112d3
--- /dev/null
+++ b/examples/animation/easing/resources.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+ <file>images/qt-logo.png</file>
+ </qresource>
+ </RCC> \ No newline at end of file
diff --git a/examples/animation/easing/window.cpp b/examples/animation/easing/window.cpp
new file mode 100644
index 0000000..c6ea360
--- /dev/null
+++ b/examples/animation/easing/window.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "window.h"
+
+Window::Window(QWidget *parent)
+ : QWidget(parent), m_iconSize(64, 64)
+{
+ m_ui.setupUi(this);
+ QButtonGroup *buttonGroup = qFindChild<QButtonGroup *>(this); // ### workaround for uic in 4.4
+ m_ui.easingCurvePicker->setIconSize(m_iconSize);
+ m_ui.easingCurvePicker->setMinimumHeight(m_iconSize.height() + 50);
+ buttonGroup->setId(m_ui.lineRadio, 0);
+ buttonGroup->setId(m_ui.circleRadio, 1);
+
+ QEasingCurve dummy;
+ m_ui.periodSpinBox->setValue(dummy.period());
+ m_ui.amplitudeSpinBox->setValue(dummy.amplitude());
+ m_ui.overshootSpinBox->setValue(dummy.overshoot());
+
+ connect(m_ui.easingCurvePicker, SIGNAL(currentRowChanged(int)), this, SLOT(curveChanged(int)));
+ connect(buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(pathChanged(int)));
+ connect(m_ui.periodSpinBox, SIGNAL(valueChanged(double)), this, SLOT(periodChanged(double)));
+ connect(m_ui.amplitudeSpinBox, SIGNAL(valueChanged(double)), this, SLOT(amplitudeChanged(double)));
+ connect(m_ui.overshootSpinBox, SIGNAL(valueChanged(double)), this, SLOT(overshootChanged(double)));
+ createCurveIcons();
+
+ QPixmap pix(QLatin1String(":/images/qt-logo.png"));
+ m_item = new PixmapItem(pix);
+ m_scene.addItem(m_item);
+ m_ui.graphicsView->setScene(&m_scene);
+
+ m_anim = new Animation(m_item, "pos");
+ m_anim->setEasingCurve(QEasingCurve::OutBounce);
+ m_ui.easingCurvePicker->setCurrentRow(int(QEasingCurve::OutBounce));
+
+ startAnimation();
+}
+
+void Window::createCurveIcons()
+{
+ QPixmap pix(m_iconSize);
+ QPainter painter(&pix);
+ QLinearGradient gradient(0,0, 0, m_iconSize.height());
+ gradient.setColorAt(0.0, QColor(240, 240, 240));
+ gradient.setColorAt(1.0, QColor(224, 224, 224));
+ QBrush brush(gradient);
+ const QMetaObject &mo = QEasingCurve::staticMetaObject;
+ QMetaEnum metaEnum = mo.enumerator(mo.indexOfEnumerator("Type"));
+ // Skip QEasingCurve::Custom
+ for (int i = 0; i < QEasingCurve::NCurveTypes - 1; ++i) {
+ painter.fillRect(QRect(QPoint(0, 0), m_iconSize), brush);
+ QEasingCurve curve((QEasingCurve::Type)i);
+ painter.setPen(QColor(0, 0, 255, 64));
+ qreal xAxis = m_iconSize.height()/1.5;
+ qreal yAxis = m_iconSize.width()/3;
+ painter.drawLine(0, xAxis, m_iconSize.width(), xAxis);
+ painter.drawLine(yAxis, 0, yAxis, m_iconSize.height());
+ painter.setPen(Qt::black);
+
+ qreal curveScale = m_iconSize.height()/2;
+ QPoint currentPos(yAxis, xAxis);
+
+ for (qreal t = 0; t < 1.0; t+=1.0/curveScale) {
+ QPoint to;
+ to.setX(yAxis + curveScale * t);
+ to.setY(xAxis - curveScale * curve.valueForProgress(t));
+ painter.drawLine(currentPos, to);
+ currentPos = to;
+ }
+ QListWidgetItem *item = new QListWidgetItem;
+ item->setIcon(QIcon(pix));
+ item->setText(metaEnum.key(i));
+ m_ui.easingCurvePicker->addItem(item);
+ }
+}
+
+void Window::startAnimation()
+{
+ m_anim->setStartValue(QPointF(0, 0));
+ m_anim->setEndValue(QPointF(100, 100));
+ m_anim->setDuration(2000);
+ m_anim->setIterationCount(-1); // forever
+ m_anim->start();
+}
+
+void Window::curveChanged(int row)
+{
+ QEasingCurve::Type curveType = (QEasingCurve::Type)row;
+ m_anim->setEasingCurve(curveType);
+ m_anim->setCurrentTime(0);
+
+ bool isElastic = curveType >= QEasingCurve::InElastic && curveType <= QEasingCurve::OutInElastic;
+ bool isBounce = curveType >= QEasingCurve::InBounce && curveType <= QEasingCurve::OutInBounce;
+ m_ui.periodSpinBox->setEnabled(isElastic);
+ m_ui.amplitudeSpinBox->setEnabled(isElastic || isBounce);
+ m_ui.overshootSpinBox->setEnabled(curveType >= QEasingCurve::InBack && curveType <= QEasingCurve::OutInBack);
+}
+
+void Window::pathChanged(int index)
+{
+ m_anim->setPathType((Animation::PathType)index);
+}
+
+void Window::periodChanged(double value)
+{
+ QEasingCurve curve = m_anim->easingCurve();
+ curve.setPeriod(value);
+ m_anim->setEasingCurve(curve);
+}
+
+void Window::amplitudeChanged(double value)
+{
+ QEasingCurve curve = m_anim->easingCurve();
+ curve.setAmplitude(value);
+ m_anim->setEasingCurve(curve);
+}
+
+void Window::overshootChanged(double value)
+{
+ QEasingCurve curve = m_anim->easingCurve();
+ curve.setOvershoot(value);
+ m_anim->setEasingCurve(curve);
+}
+
diff --git a/examples/animation/easing/window.h b/examples/animation/easing/window.h
new file mode 100644
index 0000000..4ba6eb6
--- /dev/null
+++ b/examples/animation/easing/window.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "ui_form.h"
+#include "animation.h"
+
+class PixmapItem : public QObject, public QGraphicsPixmapItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QPointF pos READ pos WRITE setPos)
+public:
+ PixmapItem(const QPixmap &pix) : QGraphicsPixmapItem(pix)
+ {
+ }
+};
+
+class Window : public QWidget {
+ Q_OBJECT
+public:
+ Window(QWidget *parent = 0);
+private slots:
+ void curveChanged(int row);
+ void pathChanged(int index);
+ void periodChanged(double);
+ void amplitudeChanged(double);
+ void overshootChanged(double);
+
+private:
+ void createCurveIcons();
+ void startAnimation();
+
+ Ui::Form m_ui;
+ QGraphicsScene m_scene;
+ PixmapItem *m_item;
+ Animation *m_anim;
+ QSize m_iconSize;
+
+
+};
diff --git a/examples/animation/example/example.pro b/examples/animation/example/example.pro
new file mode 100644
index 0000000..bc79b82
--- /dev/null
+++ b/examples/animation/example/example.pro
@@ -0,0 +1,12 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Thu Sep 25 14:03:47 2008
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+HEADERS += mainwindow.h
+SOURCES += main.cpp mainwindow.cpp
diff --git a/examples/animation/example/main.cpp b/examples/animation/example/main.cpp
new file mode 100644
index 0000000..d5f5607
--- /dev/null
+++ b/examples/animation/example/main.cpp
@@ -0,0 +1,23 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ //Q_INIT_RESOURCE(example);
+ QApplication app(argc, argv);
+ MainWindow w;
+ w.show();
+ return app.exec();
+}
+
diff --git a/examples/animation/example/mainwindow.cpp b/examples/animation/example/mainwindow.cpp
new file mode 100644
index 0000000..dfb5c70
--- /dev/null
+++ b/examples/animation/example/mainwindow.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+
+MainWindow::MainWindow() : QMainWindow(0)
+{
+ // Text edit and button
+ listWidget = new QListWidget;
+ new QListWidgetItem("Rachel", listWidget);
+ new QListWidgetItem("Andreas", listWidget);
+ new QListWidgetItem("David", listWidget);
+ new QListWidgetItem("Olivier", listWidget);
+ new QListWidgetItem("Andy", listWidget);
+ new QListWidgetItem("Martial", listWidget);
+ new QListWidgetItem("Kazou", listWidget);
+ new QListWidgetItem("Fred", listWidget);
+ new QListWidgetItem("Ingrid", listWidget);
+ QGraphicsProxyWidget *listProxy = new QGraphicsProxyWidget;
+ listProxy->setWidget(listWidget);
+
+ labelWidget = new QLabel;
+ QGraphicsProxyWidget *labelProxy = new QGraphicsProxyWidget;
+ labelProxy->setWidget(labelWidget);
+ labelWidget->setAttribute(Qt::WA_NoSystemBackground);
+
+ label2Widget = new QLabel;
+ label2Widget->setAlignment(Qt::AlignCenter);
+ QGraphicsProxyWidget *label2Proxy = new QGraphicsProxyWidget;
+ label2Proxy->setWidget(label2Widget);
+ label2Widget->setAttribute(Qt::WA_NoSystemBackground);
+
+ editWidget = new QLineEdit;
+ QGraphicsProxyWidget *editProxy = new QGraphicsProxyWidget;
+ editProxy->setWidget(editWidget);
+ editWidget->setAttribute(Qt::WA_NoSystemBackground);
+
+ // Parent widget
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ // Parent widget
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+
+ QGraphicsLinearLayout *vLayout = new QGraphicsLinearLayout(Qt::Vertical, widget);
+ vLayout->addItem(listProxy);
+ vLayout->addItem(widget2);
+ widget->setLayout(vLayout);
+
+ QPushButton *button = new QPushButton;
+ QGraphicsProxyWidget *buttonProxy = new QGraphicsProxyWidget;
+ buttonProxy->setWidget(button);
+
+ QPushButton *button2 = new QPushButton;
+ QGraphicsProxyWidget *buttonProxy2 = new QGraphicsProxyWidget;
+ buttonProxy2->setWidget(button2);
+
+ QPushButton *button3 = new QPushButton;
+ QGraphicsProxyWidget *buttonProxy3 = new QGraphicsProxyWidget;
+ buttonProxy3->setWidget(button3);
+
+ QPushButton *button4 = new QPushButton;
+ QGraphicsProxyWidget *buttonProxy4 = new QGraphicsProxyWidget;
+ buttonProxy4->setWidget(button4);
+
+ QGraphicsLinearLayout *hLayout = new QGraphicsLinearLayout(Qt::Horizontal, widget2);
+ hLayout->addItem(buttonProxy);
+ hLayout->addItem(buttonProxy2);
+ hLayout->addItem(buttonProxy3);
+ widget2->setLayout(hLayout);
+
+ scene = new QGraphicsScene(0, 0, 700, 600);
+ scene->setBackgroundBrush(scene->palette().window());
+ scene->addItem(widget);
+ scene->addItem(editProxy);
+ scene->addItem(label2Proxy);
+ scene->addItem(labelProxy);
+ scene->addItem(buttonProxy4);
+
+ machine = new QStateMachine();
+
+ group = new QState(machine->rootState());
+ state1 = new QState(group);
+ state2 = new QState(group);
+ state3 = new QState(group);
+ group->setInitialState(state1);
+
+ machine->setInitialState(group);
+
+ // State 1
+ state1->setPropertyOnEntry(button, "text", "Edit");
+ state1->setPropertyOnEntry(button2, "text", "Add");
+ state1->setPropertyOnEntry(button3, "text", "Remove");
+ state1->setPropertyOnEntry(button4, "text", "Accept");
+ state1->addTransition(button2, SIGNAL(clicked()), state3);
+ state1->setPropertyOnEntry(listProxy, "geometry", QRectF(0, 0, 700, 560));
+ state1->setPropertyOnEntry(widget, "geometry", QRectF(0, 0, 700, 600));
+ state1->setPropertyOnEntry(editProxy, "opacity", double(0));
+ state1->setPropertyOnEntry(labelProxy, "opacity", double(0));
+ state1->setPropertyOnEntry(label2Proxy, "opacity", double(0));
+ state1->setPropertyOnEntry(buttonProxy4, "opacity", double(0));
+ state1->setPropertyOnEntry(labelWidget, "text", "Name : ");
+ state1->setPropertyOnEntry(label2Widget, "text", "Edit a contact");
+ state1->setPropertyOnEntry(label2Proxy, "geometry", QRectF(375, -50, 300, 30));
+ state1->setPropertyOnEntry(labelProxy, "geometry", QRectF(350, 300, 100, 30));
+ state1->setPropertyOnEntry(editProxy, "geometry", QRectF(750, 300, 250, 30));
+ state1->setPropertyOnEntry(buttonProxy4, "geometry", QRectF(500, 350, 80, 25));
+
+ // State 2
+ state2->setPropertyOnEntry(button, "text", "Close Editing");
+ state2->setPropertyOnEntry(listProxy, "geometry", QRectF(0, 0, 350, 560));
+ state2->addTransition(button2, SIGNAL(clicked()), state3);
+ state2->addTransition(button4, SIGNAL(clicked()), state1);
+
+ state2->setPropertyOnEntry(editProxy, "opacity", double(1));
+ state2->setPropertyOnEntry(labelProxy, "opacity", double(1));
+ state2->setPropertyOnEntry(label2Proxy, "opacity", double(1));
+ state2->setPropertyOnEntry(buttonProxy4, "opacity", double(1));
+
+ state2->setPropertyOnEntry(label2Proxy, "geometry", QRectF(375, 250, 300, 30));
+ state2->setPropertyOnEntry(editProxy, "geometry", QRectF(440, 300, 260, 30));
+
+ // State 3
+ state3->setPropertyOnEntry(button4, "text", "Create New");
+ state3->setPropertyOnEntry(listProxy, "geometry", QRectF(0, 0, 350, 560));
+ state3->addTransition(button4, SIGNAL(clicked()), state1);
+ state3->addTransition(button, SIGNAL(clicked()), state1);
+ state3->setPropertyOnEntry(editProxy, "opacity", double(1));
+ state3->setPropertyOnEntry(labelProxy, "opacity", double(1));
+ state3->setPropertyOnEntry(label2Proxy, "opacity", double(1));
+ state3->setPropertyOnEntry(buttonProxy4, "opacity", double(1));
+
+ state3->setPropertyOnEntry(label2Proxy, "geometry", QRectF(375, 250, 300, 30));
+ state3->setPropertyOnEntry(editProxy, "geometry", QRectF(440, 300, 260, 30));
+
+ {
+ QAnimationGroup *animationGroup = new QParallelAnimationGroup;
+ QVariantAnimation *anim = new QPropertyAnimation(labelProxy, "opacity");
+ animationGroup->addAnimation(anim);
+ anim = new QPropertyAnimation(label2Proxy, "geometry");
+ animationGroup->addAnimation(anim);
+ anim = new QPropertyAnimation(editProxy, "geometry");
+ animationGroup->addAnimation(anim);
+ anim = new QPropertyAnimation(listProxy, "geometry");
+ animationGroup->addAnimation(anim);
+
+ state1->addAnimatedTransition(button, SIGNAL(clicked()), state2, animationGroup);
+ }
+
+ {
+ QVariantAnimation *anim;
+ QAnimationGroup *animationGroup = new QParallelAnimationGroup;
+ anim = new QPropertyAnimation(label2Proxy, "geometry");
+ animationGroup->addAnimation(anim);
+ anim = new QPropertyAnimation(editProxy, "geometry");
+ animationGroup->addAnimation(anim);
+ anim = new QPropertyAnimation(listProxy, "geometry");
+ animationGroup->addAnimation(anim);
+ state2->addAnimatedTransition(button, SIGNAL(clicked()), state1, animationGroup);
+ }
+
+ currentState = state1;
+
+ view = new QGraphicsView(scene);
+
+ setCentralWidget(view);
+
+ state3->invokeMethodOnEntry(this, "onEnterState3");
+ state2->invokeMethodOnEntry(this, "onEnterState2");
+ state1->invokeMethodOnEntry(this, "onEnterState1");
+
+ connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(onItemClicked(QListWidgetItem*)));
+ connect(button3, SIGNAL(clicked()), this, SLOT(onRemoveClicked()));
+
+ machine->start();
+}
+
+void MainWindow::onEnterState2()
+{
+ currentState = state2;
+ if (listWidget->currentItem())
+ editWidget->setText(listWidget->currentItem()->text());
+}
+
+void MainWindow::onEnterState1()
+{
+ if (currentState == state2 && listWidget->currentItem())
+ listWidget->currentItem()->setText(editWidget->text());
+ if (currentState == state3 && !editWidget->text().isNull()) {
+ new QListWidgetItem(editWidget->text(), listWidget);
+ editWidget->clear();
+ }
+ currentState = state1;
+}
+
+void MainWindow::onEnterState3()
+{
+ currentState = state3;
+}
+
+void MainWindow::onItemClicked(QListWidgetItem*)
+{
+ if (currentState == state2)
+ {
+ editWidget->setText(listWidget->currentItem()->text());
+ editWidget->clear();
+ }
+}
+
+void MainWindow::onRemoveClicked()
+{
+ QListWidgetItem *listItem = listWidget->takeItem(listWidget->currentRow());
+ delete listItem;
+}
diff --git a/examples/animation/example/mainwindow.h b/examples/animation/example/mainwindow.h
new file mode 100644
index 0000000..6be7463
--- /dev/null
+++ b/examples/animation/example/mainwindow.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __MAINWINDOW__H__
+#define __MAINWINDOW__H__
+
+#include <QtGui>
+
+class MainWindow : public QMainWindow
+{
+Q_OBJECT
+public:
+ MainWindow();
+
+private slots :
+ void onEnterState3();
+ void onEnterState2();
+ void onEnterState1();
+ void onItemClicked(QListWidgetItem*);
+ void onRemoveClicked();
+private:
+ QListWidget *listWidget;
+ QLabel *labelWidget;
+ QLabel *label2Widget;
+ QLineEdit *editWidget;
+ QGraphicsScene *scene;
+ QGraphicsView *view;
+ QState *state1;
+ QState *state2;
+ QState *state3;
+ QState *currentState;
+ QState *group;
+ QStateMachine *machine;
+};
+
+#endif //__MAINWINDOW__H__
+
diff --git a/examples/animation/moveblocks/main.cpp b/examples/animation/moveblocks/main.cpp
new file mode 100644
index 0000000..f4c754d
--- /dev/null
+++ b/examples/animation/moveblocks/main.cpp
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <QtGui>
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+#include "qstatemachine.h"
+#include "qabstracttransition.h"
+#include "qanimationstate.h"
+#include "qpropertyanimation.h"
+#include "qsequentialanimationgroup.h"
+#include "qparallelanimationgroup.h"
+#include "qgraphicswidget.h"
+#endif
+#include <time.h>
+
+class StateSwitchEvent: public QEvent
+{
+public:
+ StateSwitchEvent()
+ : QEvent(Type(StateSwitchType))
+ {
+ }
+
+ StateSwitchEvent(int rand)
+ : QEvent(Type(StateSwitchType)),
+ m_rand(rand)
+ {
+ }
+
+ enum { StateSwitchType = QEvent::User + 256 };
+
+ int rand() const { return m_rand; }
+
+private:
+ int m_rand;
+};
+
+
+class QGraphicsRectWidget : public QGraphicsWidget
+{
+public:
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *,
+ QWidget *)
+ {
+ painter->fillRect(rect(), Qt::blue);
+ }
+};
+
+class StateSwitchTransition: public QAbstractTransition
+{
+public:
+ StateSwitchTransition(int rand)
+ : QAbstractTransition(),
+ m_rand(rand)
+ {
+ }
+
+protected:
+ virtual bool eventTest(QEvent *event) const
+ {
+ return (event->type() == QEvent::Type(StateSwitchEvent::StateSwitchType))
+ && (static_cast<StateSwitchEvent *>(event)->rand() == m_rand);
+ }
+
+ virtual void onTransition() {}
+
+private:
+ int m_rand;
+};
+
+class StateSwitcher : public QState
+{
+ Q_OBJECT
+public:
+ StateSwitcher(QStateMachine *machine)
+ : QState(machine->rootState()), m_machine(machine),
+ m_stateCount(0), m_lastIndex(0)
+ { }
+
+ virtual void onEntry()
+ {
+ int n;
+ while ((n = (qrand() % m_stateCount + 1)) == m_lastIndex)
+ { }
+ m_lastIndex = n;
+ m_machine->postEvent(new StateSwitchEvent(n));
+ }
+ virtual void onExit() {}
+
+ void addState(QState *state, QAbstractAnimation *animation) {
+ StateSwitchTransition *trans = new StateSwitchTransition(++m_stateCount);
+ trans->setTargetState(state);
+ addAnimatedTransition(trans, animation);
+ }
+
+
+private:
+ QStateMachine *m_machine;
+ int m_stateCount;
+ int m_lastIndex;
+};
+
+QState *createGeometryState(QObject *w1, const QRect &rect1,
+ QObject *w2, const QRect &rect2,
+ QObject *w3, const QRect &rect3,
+ QObject *w4, const QRect &rect4,
+ QState *parent)
+{
+ QState *result = new QState(parent);
+ result->setPropertyOnEntry(w1, "geometry", rect1);
+ result->setPropertyOnEntry(w1, "geometry", rect1);
+ result->setPropertyOnEntry(w2, "geometry", rect2);
+ result->setPropertyOnEntry(w3, "geometry", rect3);
+ result->setPropertyOnEntry(w4, "geometry", rect4);
+
+ return result;
+}
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+#if 0
+ QWidget window;
+ QPalette palette;
+ palette.setBrush(QPalette::Window, Qt::black);
+ window.setPalette(palette);
+ QPushButton *button1 = new QPushButton("A", &window);
+ QPushButton *button2 = new QPushButton("B", &window);
+ QPushButton *button3 = new QPushButton("C", &window);
+ QPushButton *button4 = new QPushButton("D", &window);
+
+ button1->setObjectName("button1");
+ button2->setObjectName("button2");
+ button3->setObjectName("button3");
+ button4->setObjectName("button4");
+#else
+ QGraphicsRectWidget *button1 = new QGraphicsRectWidget;
+ QGraphicsRectWidget *button2 = new QGraphicsRectWidget;
+ QGraphicsRectWidget *button3 = new QGraphicsRectWidget;
+ QGraphicsRectWidget *button4 = new QGraphicsRectWidget;
+ button2->setZValue(1);
+ button3->setZValue(2);
+ button4->setZValue(3);
+ QGraphicsScene scene(0, 0, 300, 300);
+ scene.setBackgroundBrush(Qt::black);
+ scene.addItem(button1);
+ scene.addItem(button2);
+ scene.addItem(button3);
+ scene.addItem(button4);
+
+ QGraphicsView window(&scene);
+ window.setFrameStyle(0);
+ window.setAlignment(Qt::AlignLeft | Qt::AlignTop);
+ window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+#endif
+ QStateMachine machine;
+
+ QState *group = new QState();
+ group->setObjectName("group");
+ QTimer timer;
+ timer.setInterval(1250);
+ timer.setSingleShot(true);
+ group->invokeMethodOnEntry(&timer, "start");
+
+ QState *state1;
+ QState *state2;
+ QState *state3;
+ QState *state4;
+ QState *state5;
+ QState *state6;
+ QState *state7;
+
+ state1 = createGeometryState(button1, QRect(100, 0, 50, 50),
+ button2, QRect(150, 0, 50, 50),
+ button3, QRect(200, 0, 50, 50),
+ button4, QRect(250, 0, 50, 50),
+ group);
+ state2 = createGeometryState(button1, QRect(250, 100, 50, 50),
+ button2, QRect(250, 150, 50, 50),
+ button3, QRect(250, 200, 50, 50),
+ button4, QRect(250, 250, 50, 50),
+ group);
+ state3 = createGeometryState(button1, QRect(150, 250, 50, 50),
+ button2, QRect(100, 250, 50, 50),
+ button3, QRect(50, 250, 50, 50),
+ button4, QRect(0, 250, 50, 50),
+ group);
+ state4 = createGeometryState(button1, QRect(0, 150, 50, 50),
+ button2, QRect(0, 100, 50, 50),
+ button3, QRect(0, 50, 50, 50),
+ button4, QRect(0, 0, 50, 50),
+ group);
+ state5 = createGeometryState(button1, QRect(100, 100, 50, 50),
+ button2, QRect(150, 100, 50, 50),
+ button3, QRect(100, 150, 50, 50),
+ button4, QRect(150, 150, 50, 50),
+ group);
+ state6 = createGeometryState(button1, QRect(50, 50, 50, 50),
+ button2, QRect(200, 50, 50, 50),
+ button3, QRect(50, 200, 50, 50),
+ button4, QRect(200, 200, 50, 50),
+ group);
+ state7 = createGeometryState(button1, QRect(0, 0, 50, 50),
+ button2, QRect(250, 0, 50, 50),
+ button3, QRect(0, 250, 50, 50),
+ button4, QRect(250, 250, 50, 50),
+ group);
+ group->setInitialState(state1);
+
+ QParallelAnimationGroup animationGroup;
+ QSequentialAnimationGroup *subGroup;
+
+ QPropertyAnimation *anim = new QPropertyAnimation(button4, "geometry");
+ anim->setDuration(1000);
+ anim->setEasingCurve(QEasingCurve::OutElastic);
+ animationGroup.addAnimation(anim);
+
+ subGroup = new QSequentialAnimationGroup(&animationGroup);
+ subGroup->addPause(100);
+ anim = new QPropertyAnimation(button3, "geometry");
+ anim->setDuration(1000);
+ anim->setEasingCurve(QEasingCurve::OutElastic);
+ subGroup->addAnimation(anim);
+
+ subGroup = new QSequentialAnimationGroup(&animationGroup);
+ subGroup->addPause(150);
+ anim = new QPropertyAnimation(button2, "geometry");
+ anim->setDuration(1000);
+ anim->setEasingCurve(QEasingCurve::OutElastic);
+ subGroup->addAnimation(anim);
+
+ subGroup = new QSequentialAnimationGroup(&animationGroup);
+ subGroup->addPause(200);
+ anim = new QPropertyAnimation(button1, "geometry");
+ anim->setDuration(1000);
+ anim->setEasingCurve(QEasingCurve::OutElastic);
+ subGroup->addAnimation(anim);
+
+ StateSwitcher *stateSwitcher = new StateSwitcher(&machine);
+ stateSwitcher->setObjectName("stateSwitcher");
+ group->addTransition(&timer, SIGNAL(timeout()), stateSwitcher);
+ stateSwitcher->addState(state1, &animationGroup);
+ stateSwitcher->addState(state2, &animationGroup);
+ stateSwitcher->addState(state3, &animationGroup);
+ stateSwitcher->addState(state4, &animationGroup);
+ stateSwitcher->addState(state5, &animationGroup);
+ stateSwitcher->addState(state6, &animationGroup);
+ stateSwitcher->addState(state7, &animationGroup);
+
+ machine.addState(group);
+ machine.setInitialState(group);
+ machine.start();
+
+
+ window.resize(300, 300);
+ window.show();
+
+ qsrand(time(0));
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/examples/animation/moveblocks/moveblocks.pro b/examples/animation/moveblocks/moveblocks.pro
new file mode 100644
index 0000000..7a82ca5
--- /dev/null
+++ b/examples/animation/moveblocks/moveblocks.pro
@@ -0,0 +1,8 @@
+# Input
+SOURCES += main.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/animation/moveblocks
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS states.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/animation/moveblocks
+INSTALLS += target sources
diff --git a/examples/animation/padnavigator-ng/backside.ui b/examples/animation/padnavigator-ng/backside.ui
new file mode 100644
index 0000000..afa488c
--- /dev/null
+++ b/examples/animation/padnavigator-ng/backside.ui
@@ -0,0 +1,208 @@
+<ui version="4.0" >
+ <class>BackSide</class>
+ <widget class="QWidget" name="BackSide" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>378</width>
+ <height>385</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>BackSide</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2" >
+ <item>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="title" >
+ <string>Settings</string>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Title:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="hostName" >
+ <property name="text" >
+ <string>Pad Navigator Example</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Modified:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_3" >
+ <property name="text" >
+ <string>Extent</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <layout class="QHBoxLayout" name="horizontalLayout" >
+ <item>
+ <widget class="QSlider" name="horizontalSlider" >
+ <property name="value" >
+ <number>42</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="spinBox" >
+ <property name="value" >
+ <number>42</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QDateTimeEdit" name="dateTimeEdit" />
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2" >
+ <property name="title" >
+ <string>Other input</string>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2" >
+ <item>
+ <widget class="QTreeWidget" name="treeWidget" >
+ <column>
+ <property name="text" >
+ <string>Widgets On Graphics View</string>
+ </property>
+ </column>
+ <item>
+ <property name="text" >
+ <string>QGraphicsProxyWidget</string>
+ </property>
+ <item>
+ <property name="text" >
+ <string>QGraphicsWidget</string>
+ </property>
+ <item>
+ <property name="text" >
+ <string>QObject</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>QGraphicsItem</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>QGraphicsLayoutItem</string>
+ </property>
+ </item>
+ </item>
+ </item>
+ <item>
+ <property name="text" >
+ <string>QGraphicsGridLayout</string>
+ </property>
+ <item>
+ <property name="text" >
+ <string>QGraphicsLayout</string>
+ </property>
+ <item>
+ <property name="text" >
+ <string>QGraphicsLayoutItem</string>
+ </property>
+ </item>
+ </item>
+ </item>
+ <item>
+ <property name="text" >
+ <string>QGraphicsLinearLayout</string>
+ </property>
+ <item>
+ <property name="text" >
+ <string>QGraphicsLayout</string>
+ </property>
+ <item>
+ <property name="text" >
+ <string>QGraphicsLayoutItem</string>
+ </property>
+ </item>
+ </item>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>groupBox</tabstop>
+ <tabstop>hostName</tabstop>
+ <tabstop>dateTimeEdit</tabstop>
+ <tabstop>horizontalSlider</tabstop>
+ <tabstop>spinBox</tabstop>
+ <tabstop>groupBox_2</tabstop>
+ <tabstop>treeWidget</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>horizontalSlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>spinBox</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>184</x>
+ <y>125</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>275</x>
+ <y>127</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>spinBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>horizontalSlider</receiver>
+ <slot>setValue(int)</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>272</x>
+ <y>114</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>190</x>
+ <y>126</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/examples/animation/padnavigator-ng/images/artsfftscope.png b/examples/animation/padnavigator-ng/images/artsfftscope.png
new file mode 100644
index 0000000..b4b8775
--- /dev/null
+++ b/examples/animation/padnavigator-ng/images/artsfftscope.png
Binary files differ
diff --git a/examples/animation/padnavigator-ng/images/blue_angle_swirl.jpg b/examples/animation/padnavigator-ng/images/blue_angle_swirl.jpg
new file mode 100644
index 0000000..5bf0deb
--- /dev/null
+++ b/examples/animation/padnavigator-ng/images/blue_angle_swirl.jpg
Binary files differ
diff --git a/examples/animation/padnavigator-ng/images/kontact_contacts.png b/examples/animation/padnavigator-ng/images/kontact_contacts.png
new file mode 100644
index 0000000..6fb4cc8
--- /dev/null
+++ b/examples/animation/padnavigator-ng/images/kontact_contacts.png
Binary files differ
diff --git a/examples/animation/padnavigator-ng/images/kontact_journal.png b/examples/animation/padnavigator-ng/images/kontact_journal.png
new file mode 100644
index 0000000..b1fedb6
--- /dev/null
+++ b/examples/animation/padnavigator-ng/images/kontact_journal.png
Binary files differ
diff --git a/examples/animation/padnavigator-ng/images/kontact_mail.png b/examples/animation/padnavigator-ng/images/kontact_mail.png
new file mode 100644
index 0000000..672f8fa
--- /dev/null
+++ b/examples/animation/padnavigator-ng/images/kontact_mail.png
Binary files differ
diff --git a/examples/animation/padnavigator-ng/images/kontact_notes.png b/examples/animation/padnavigator-ng/images/kontact_notes.png
new file mode 100644
index 0000000..229bf73
--- /dev/null
+++ b/examples/animation/padnavigator-ng/images/kontact_notes.png
Binary files differ
diff --git a/examples/animation/padnavigator-ng/images/kopeteavailable.png b/examples/animation/padnavigator-ng/images/kopeteavailable.png
new file mode 100644
index 0000000..2eaf41a
--- /dev/null
+++ b/examples/animation/padnavigator-ng/images/kopeteavailable.png
Binary files differ
diff --git a/examples/animation/padnavigator-ng/images/metacontact_online.png b/examples/animation/padnavigator-ng/images/metacontact_online.png
new file mode 100644
index 0000000..6a398dd
--- /dev/null
+++ b/examples/animation/padnavigator-ng/images/metacontact_online.png
Binary files differ
diff --git a/examples/animation/padnavigator-ng/images/minitools.png b/examples/animation/padnavigator-ng/images/minitools.png
new file mode 100644
index 0000000..0248c9d
--- /dev/null
+++ b/examples/animation/padnavigator-ng/images/minitools.png
Binary files differ
diff --git a/examples/animation/padnavigator-ng/main.cpp b/examples/animation/padnavigator-ng/main.cpp
new file mode 100644
index 0000000..5b35b62
--- /dev/null
+++ b/examples/animation/padnavigator-ng/main.cpp
@@ -0,0 +1,24 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include "panel.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ Q_INIT_RESOURCE(padnavigator);
+
+ Panel panel(3, 3);
+ panel.show();
+
+ return app.exec();
+}
diff --git a/examples/animation/padnavigator-ng/padnavigator.pro b/examples/animation/padnavigator-ng/padnavigator.pro
new file mode 100644
index 0000000..0d094c6
--- /dev/null
+++ b/examples/animation/padnavigator-ng/padnavigator.pro
@@ -0,0 +1,24 @@
+HEADERS += \
+ panel.h \
+ roundrectitem.h \
+ splashitem.h
+
+SOURCES += \
+ panel.cpp \
+ roundrectitem.cpp \
+ splashitem.cpp \
+ main.cpp
+
+RESOURCES += \
+ padnavigator.qrc
+
+FORMS += \
+ backside.ui
+
+contains(QT_CONFIG, opengl):QT += opengl
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/padnavigator
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS padnavigator.pro images
+sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/padnavigator
+INSTALLS += target sources
diff --git a/examples/animation/padnavigator-ng/padnavigator.qrc b/examples/animation/padnavigator-ng/padnavigator.qrc
new file mode 100644
index 0000000..30ee8e1
--- /dev/null
+++ b/examples/animation/padnavigator-ng/padnavigator.qrc
@@ -0,0 +1,14 @@
+<RCC>
+ <qresource>
+ <file>images/blue_angle_swirl.jpg</file>
+ <file>images/artsfftscope.png</file>
+ <file>images/kontact_contacts.png</file>
+ <file>images/kontact_journal.png</file>
+ <file>images/kontact_mail.png</file>
+ <file>images/kontact_notes.png</file>
+ <file>images/kopeteavailable.png</file>
+ <file>images/metacontact_online.png</file>
+ <file>images/minitools.png</file>
+ <file>images/blue_angle_swirl.jpg</file>
+ </qresource>
+</RCC>
diff --git a/examples/animation/padnavigator-ng/panel.cpp b/examples/animation/padnavigator-ng/panel.cpp
new file mode 100644
index 0000000..94dbdec
--- /dev/null
+++ b/examples/animation/padnavigator-ng/panel.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "panel.h"
+#include "roundrectitem.h"
+#include "splashitem.h"
+#include "ui_backside.h"
+
+#ifndef QT_NO_OPENGL
+#include <QtOpenGL/QtOpenGL>
+#else
+#endif
+#include <QtGui/QtGui>
+
+Panel::Panel(int width, int height)
+ : selectedIndex(0),
+ grid(width*height),
+ width(width),
+ height(height),
+ flipped(false),
+ flippingGroup(0),
+ rotationXanim(0),
+ rotationYanim(0)
+{
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setCacheMode(CacheBackground);
+ setViewportUpdateMode(FullViewportUpdate);
+ setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
+ setBackgroundBrush(QPixmap(":/images/blue_angle_swirl.jpg"));
+#ifndef QT_NO_OPENGL
+ setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
+#endif
+
+ QRectF bounds((-width / 2.0) * 150, (-height / 2.0) * 150, width * 150, height * 150);
+
+ setScene(new QGraphicsScene(bounds, this));
+
+ baseItem = new RoundRectItem(bounds, QColor(226, 255, 92, 64));
+ scene()->addItem(baseItem);
+
+ QWidget *embed = new QWidget;
+ ui = new Ui_BackSide;
+ ui->setupUi(embed);
+ ui->hostName->setFocus();
+
+ backItem = new RoundRectItem(bounds, embed->palette().window(), embed);
+ backItem->setYRotation(180);
+ backItem->setParentItem(baseItem);
+
+ selectionItem = new RoundRectItem(QRectF(-60, -60, 120, 120), Qt::gray);
+ selectionItem->setParentItem(baseItem);
+ selectionItem->setZValue(-1);
+ selectionItem->setPos(posForLocation(0));
+
+ int currentIndex = 0;
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ RoundRectItem *item = new RoundRectItem(QRectF(-54, -54, 108, 108),
+ QColor(214, 240, 110, 128));
+ item->setPos(posForLocation(currentIndex));
+
+ item->setParentItem(baseItem);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ grid[currentIndex++] = item;
+
+ switch (qrand() % 9) {
+ case 0: item->setPixmap(QPixmap(":/images/kontact_contacts.png")); break;
+ case 1: item->setPixmap(QPixmap(":/images/kontact_journal.png")); break;
+ case 2: item->setPixmap(QPixmap(":/images/kontact_notes.png")); break;
+ case 3: item->setPixmap(QPixmap(":/images/kopeteavailable.png")); break;
+ case 4: item->setPixmap(QPixmap(":/images/metacontact_online.png")); break;
+ case 5: item->setPixmap(QPixmap(":/images/minitools.png")); break;
+ case 6: item->setPixmap(QPixmap(":/images/kontact_journal.png")); break;
+ case 7: item->setPixmap(QPixmap(":/images/kontact_contacts.png")); break;
+ case 8: item->setPixmap(QPixmap(":/images/kopeteavailable.png")); break;
+ default:
+ break;
+ }
+
+ connect(item, SIGNAL(activated()), this, SLOT(flip()));
+ }
+ }
+
+ grid.first()->setFocus();
+
+ connect(backItem, SIGNAL(activated()),
+ this, SLOT(flip()));
+
+ splash = new SplashItem;
+ splash->setZValue(5);
+ splash->setPos(-splash->rect().width() / 2, scene()->sceneRect().top());
+ scene()->addItem(splash);
+
+ splash->grabKeyboard();
+
+ //initialize the position
+ baseItem->setYRotation(selectionItem->x()/6.);
+ baseItem->setXRotation(selectionItem->y()/6.);
+
+ setWindowTitle(tr("Pad Navigator Example"));
+}
+
+Panel::~Panel()
+{
+}
+
+void Panel::keyPressEvent(QKeyEvent *event)
+{
+ if (splash->isVisible() || event->key() == Qt::Key_Return || flipped) {
+ QGraphicsView::keyPressEvent(event);
+ return;
+ }
+
+ selectedIndex = (selectedIndex + grid.count() + (event->key() == Qt::Key_Right) - (event->key() == Qt::Key_Left)
+ + width * ((event->key() == Qt::Key_Down) - (event->key() == Qt::Key_Up))) % grid.count();
+ grid[selectedIndex]->setFocus();
+
+ const QPointF pos = posForLocation(selectedIndex);
+
+ const double angleY = pos.x() / 6.,
+ angleX = pos.y() / 6.;
+
+ QAnimationGroup *group = new QParallelAnimationGroup();
+
+ QVariantAnimation *anim = new QPropertyAnimation(baseItem, "xRotation");
+ anim->setEndValue(angleX);
+ anim->setDuration(150);
+ anim->setEasingCurve(QEasingCurve::OutInSine);
+ group->addAnimation(anim);
+
+ anim = new QPropertyAnimation(baseItem, "yRotation");
+ anim->setEndValue(angleY);
+ anim->setDuration(150);
+ anim->setEasingCurve(QEasingCurve::OutInSine);
+ group->addAnimation(anim);
+
+ anim = new QPropertyAnimation(selectionItem, "pos");
+ anim->setEndValue(pos);
+ anim->setDuration(150);
+ anim->setEasingCurve(QEasingCurve::Linear);
+ group->addAnimation(anim);
+
+ group->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
+void Panel::resizeEvent(QResizeEvent *event)
+{
+ QGraphicsView::resizeEvent(event);
+ fitInView(scene()->sceneRect(), Qt::KeepAspectRatio);
+}
+
+void Panel::flip()
+{
+ grid[selectedIndex]->setFocus();
+
+ if (flippingGroup == 0) {
+ flippingGroup = new QParallelAnimationGroup(this);
+
+ const qreal zoomOut = qreal(.75);
+
+ //slight scaling down while flipping
+ QVariantAnimation *anim = new QPropertyAnimation(baseItem, "yScale");
+ anim->setKeyValueAt(qreal(.5), zoomOut);
+ anim->setEndValue(1);
+ anim->setEasingCurve(QEasingCurve::OutInSine);
+ anim->setDuration(500);
+ flippingGroup->addAnimation(anim);
+
+ anim = new QPropertyAnimation(baseItem, "xScale");
+ anim->setKeyValueAt(qreal(.5), zoomOut);
+ anim->setEndValue(1);
+ anim->setEasingCurve(QEasingCurve::OutInSine);
+ anim->setDuration(500);
+ flippingGroup->addAnimation(anim);
+
+ rotationXanim = new QPropertyAnimation(baseItem, "xRotation");
+ rotationXanim->setEndValue(0);
+ rotationXanim->setDuration(500);
+ flippingGroup->addAnimation(rotationXanim);
+
+ rotationYanim = new QPropertyAnimation(baseItem, "yRotation");
+ rotationYanim->setEndValue(180);
+ rotationYanim->setDuration(500);
+ flippingGroup->addAnimation(rotationYanim);
+ }
+
+ if (flippingGroup->currentTime() != 0 && flippingGroup->direction() == QAbstractAnimation::Forward) {
+ flippingGroup->setDirection(QAbstractAnimation::Backward);
+ } else {
+ flippingGroup->setDirection(QAbstractAnimation::Forward);
+ if (flippingGroup->currentTime() == 0) {
+ //we always make sure when it is at the beginning
+ rotationXanim->setStartValue(baseItem->xRotation());
+ rotationYanim->setStartValue(baseItem->yRotation());
+ }
+ }
+ flippingGroup->start();
+ flipped = !flipped;
+}
+
+QPointF Panel::posForLocation(int index) const
+{
+ const int x = index % width,
+ y = index / width;
+ return QPointF(x * 150, y * 150)
+ - QPointF((width - 1) * 75, (height - 1) * 75);
+}
diff --git a/examples/animation/padnavigator-ng/panel.h b/examples/animation/padnavigator-ng/panel.h
new file mode 100644
index 0000000..cbceed1
--- /dev/null
+++ b/examples/animation/padnavigator-ng/panel.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qgraphicsview.h>
+#ifdef QT_EXPERIMENTAL_SOLUTION
+#include "qtgraphicswidget.h"
+#else
+#include <QtGui/qgraphicswidget.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+class Ui_BackSide;
+QT_END_NAMESPACE;
+
+class RoundRectItem;
+class QAnimationGroup;
+class QPropertyAnimation;
+
+class Panel : public QGraphicsView
+{
+ Q_OBJECT
+public:
+ Panel(int width, int height);
+ ~Panel();
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+ void resizeEvent(QResizeEvent *event);
+
+private Q_SLOTS:
+ void flip();
+
+private:
+ QPointF posForLocation(int index) const;
+
+ QGraphicsWidget *selectionItem;
+ QGraphicsWidget *baseItem;
+ RoundRectItem *backItem;
+ QGraphicsWidget *splash;
+ int selectedIndex;
+
+ QVector<QGraphicsItem*> grid;
+
+ int width;
+ int height;
+ bool flipped;
+ Ui_BackSide *ui;
+
+ QAnimationGroup *flippingGroup;
+ QPropertyAnimation *rotationXanim, *rotationYanim;
+};
diff --git a/examples/animation/padnavigator-ng/roundrectitem.cpp b/examples/animation/padnavigator-ng/roundrectitem.cpp
new file mode 100644
index 0000000..e498538
--- /dev/null
+++ b/examples/animation/padnavigator-ng/roundrectitem.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "roundrectitem.h"
+
+#include <QtGui/QtGui>
+
+RoundRectItem::RoundRectItem(const QRectF &rect, const QBrush &brush, QWidget *embeddedWidget)
+ : QGraphicsWidget(),
+ brush(brush),
+ proxyWidget(0),
+ m_rect(rect)
+{
+ if (embeddedWidget) {
+ proxyWidget = new QGraphicsProxyWidget(this);
+ proxyWidget->setFocusPolicy(Qt::StrongFocus);
+ proxyWidget->setWidget(embeddedWidget);
+ }
+}
+
+void RoundRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ const bool widgetHidden = parentItem() == 0 || qAbs(static_cast<QGraphicsWidget*>(parentItem())->yRotation()) < 90;
+
+ if (proxyWidget) {
+ if (widgetHidden) {
+ proxyWidget->hide();
+ } else {
+ if (!proxyWidget->isVisible()) {
+ proxyWidget->setGeometry(boundingRect().adjusted(25, 25, -25, -25));
+ proxyWidget->show();
+ proxyWidget->setFocus();
+ }
+ painter->setBrush(brush);
+ painter->setPen(QPen(Qt::black, 1));
+ painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
+ painter->drawRoundRect(m_rect);
+ }
+ } else if (widgetHidden) {
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(QColor(0, 0, 0, 64));
+ painter->drawRoundRect(m_rect.translated(2, 2));
+
+ QLinearGradient gradient(m_rect.topLeft(), m_rect.bottomRight());
+ const QColor col = brush.color();
+ gradient.setColorAt(0, col);
+ gradient.setColorAt(1, col.dark(200));
+ painter->setBrush(gradient);
+ painter->setPen(QPen(Qt::black, 1));
+ painter->drawRoundRect(m_rect);
+ if (!pix.isNull()) {
+ painter->scale(qreal(1.95), qreal(1.95));
+ painter->drawPixmap(-pix.width() / 2, -pix.height() / 2, pix);
+ }
+ }
+
+}
+
+QRectF RoundRectItem::boundingRect() const
+{
+ qreal penW = qreal(.5);
+ qreal shadowW = 2;
+ return m_rect.adjusted(-penW, -penW, penW + shadowW, penW + shadowW);
+}
+
+void RoundRectItem::setPixmap(const QPixmap &pixmap)
+{
+ pix = pixmap;
+ if (scene() && isVisible())
+ update();
+}
+
+void RoundRectItem::keyPressEvent(QKeyEvent *event)
+{
+ if (event->isAutoRepeat() || event->key() != Qt::Key_Return) {
+ QGraphicsWidget::keyPressEvent(event);
+ return;
+ }
+
+ if (!proxyWidget) {
+ setXScale(qreal(.9));
+ setYScale(qreal(.9));
+ }
+ emit activated();
+}
+
+void RoundRectItem::keyReleaseEvent(QKeyEvent *event)
+{
+ if (event->isAutoRepeat() || event->key() != Qt::Key_Return) {
+ QGraphicsWidget::keyReleaseEvent(event);
+ return;
+ }
+
+ if (!proxyWidget) {
+ setXScale(1);
+ setYScale(1);
+ }
+}
diff --git a/examples/animation/padnavigator-ng/roundrectitem.h b/examples/animation/padnavigator-ng/roundrectitem.h
new file mode 100644
index 0000000..56a6d3c
--- /dev/null
+++ b/examples/animation/padnavigator-ng/roundrectitem.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qobject.h>
+#include <QtGui/qbrush.h>
+#ifdef QT_EXPERIMENTAL_SOLUTION
+#include "qtgraphicswidget.h"
+#else
+#include <QtGui/qgraphicswidget.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+class QGraphicsProxyWidget;
+QT_END_NAMESPACE;
+
+class RoundRectItem : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ RoundRectItem(const QRectF &rect, const QBrush &brush, QWidget *embeddedWidget = 0);
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *);
+ QRectF boundingRect() const;
+
+ void setPixmap(const QPixmap &pixmap);
+
+Q_SIGNALS:
+ void activated();
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *event);
+
+private:
+ QRectF m_rect;
+ QBrush brush;
+ QPixmap pix;
+ QGraphicsProxyWidget *proxyWidget;
+};
diff --git a/examples/animation/padnavigator-ng/splashitem.cpp b/examples/animation/padnavigator-ng/splashitem.cpp
new file mode 100644
index 0000000..84a8945
--- /dev/null
+++ b/examples/animation/padnavigator-ng/splashitem.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "splashitem.h"
+
+#include <QtGui/QtGui>
+
+SplashItem::SplashItem(QGraphicsItem *parent)
+ : QGraphicsWidget(parent)
+{
+
+ text = tr("Welcome to the Pad Navigator Example. You can use the"
+ " keyboard arrows to navigate the icons, and press enter"
+ " to activate an item. Please press any key to continue.");
+ resize(400, 175);
+}
+
+void SplashItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ painter->setPen(QPen(Qt::black, 2));
+ painter->setBrush(QColor(245, 245, 255, 220));
+ painter->setClipRect(rect());
+ painter->drawRoundRect(3, -100 + 3, 400 - 6, 250 - 6);
+
+ QRectF textRect = rect().adjusted(10, 10, -10, -10);
+ int flags = Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap;
+
+ QFont font;
+ font.setPixelSize(18);
+ painter->setPen(Qt::black);
+ painter->setFont(font);
+ painter->drawText(textRect, flags, text);
+}
+
+void SplashItem::keyPressEvent(QKeyEvent * /* event */)
+{
+ QVariantAnimation *anim = new QPropertyAnimation(this, "pos");
+ anim->setEndValue(QPointF(x(), scene()->sceneRect().top() - rect().height()));
+ anim->setDuration(350);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+
+ anim = new QPropertyAnimation(this, "opacity");
+ anim->setEndValue(0);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+
+ connect(anim, SIGNAL(finished()), SLOT(close()));
+}
diff --git a/examples/animation/padnavigator-ng/splashitem.h b/examples/animation/padnavigator-ng/splashitem.h
new file mode 100644
index 0000000..6428b69
--- /dev/null
+++ b/examples/animation/padnavigator-ng/splashitem.h
@@ -0,0 +1,31 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qobject.h>
+#ifdef QT_EXPERIMENTAL_SOLUTION
+#include "qtgraphicswidget.h"
+#else
+#include <QtGui/qgraphicswidget.h>
+#endif
+
+class SplashItem : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ SplashItem(QGraphicsItem *parent = 0);
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+
+private:
+ QString text;
+};
diff --git a/examples/animation/photobrowser/main.cpp b/examples/animation/photobrowser/main.cpp
new file mode 100644
index 0000000..98f2a9e
--- /dev/null
+++ b/examples/animation/photobrowser/main.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "river.h"
+#include "menu.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ if (app.arguments().size() == 1) {
+ qWarning("you have to specifiy a path to look for the photos");
+ return 0;
+ }
+
+
+ QGraphicsScene scene;
+ scene.setSceneRect(QRectF(QPointF(), River::fixedSize()));
+
+ QGraphicsView view(&scene);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+ const int fw = view.frameWidth() * 2;
+ view.setFixedSize(River::fixedSize() + QSize(fw,fw));
+
+ River river(app.arguments()[1]);
+ scene.addItem(&river);
+
+ Menu menu(&river);
+ menu.addAction(QLatin1String("River Mode"), &river, SLOT(setRiverMode()));
+ menu.addAction(QLatin1String("Grid Mode"), &river, SLOT(setGridMode()));
+ menu.addAction(QLatin1String("Cover Flow"), &river, SLOT(setCoverMode()));
+ menu.addAction(QLatin1String("Hide Menu"), &menu, SLOT(hide()));
+ menu.addAction(QLatin1String("Exit"), &app, SLOT(quit()));
+ menu.setZValue(2);
+ menu.setFocus();
+
+ river.menu = &menu;
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/animation/photobrowser/menu.cpp b/examples/animation/photobrowser/menu.cpp
new file mode 100644
index 0000000..d4efe9c
--- /dev/null
+++ b/examples/animation/photobrowser/menu.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "menu.h"
+
+Menu::Menu(QGraphicsItem *parent) : QGraphicsWidget(parent), m_selected(0)
+{
+ setFlag(QGraphicsItem::ItemIsFocusable);
+ m_selection = new QGraphicsRectItem(this);
+ QLinearGradient linearGrad(QPointF(0, 0), QPointF(0,50));
+ linearGrad.setColorAt(0, QColor(255,255,255,128));
+ linearGrad.setColorAt(1, QColor(255,255,255,16));
+ m_selection->setBrush(linearGrad);
+ m_selection->setPen(QPen(Qt::transparent));
+}
+
+Menu::~Menu()
+{
+}
+
+
+MenuAction *Menu::addAction(const QString &text, QObject *receiver, const char* slot)
+{
+ MenuAction *action = new MenuAction(text, this);
+ if (!m_actions.isEmpty()) {
+ MenuAction *last = m_actions.last();
+ action->setPos(last->pos() + last->boundingRect().bottomLeft());
+ }
+ m_actions.append(action);
+ if (m_selection->boundingRect().width() < action->boundingRect().width())
+ m_selection->setRect(action->boundingRect());
+
+ QObject::connect(action, SIGNAL(triggered()), receiver, slot);
+ return action;
+}
+
+QRectF Menu::boundingRect() const
+{
+ QRectF res;
+ foreach (MenuAction *a, m_actions)
+ res |= a->boundingRect();
+ return res;
+}
+
+void Menu::keyPressEvent (QKeyEvent * event)
+{
+ switch (event->key()) {
+ case Qt::Key_Escape:
+ hide();
+ break;
+ case Qt::Key_Up:
+ m_selected -= 2;
+ case Qt::Key_Down:
+ if (!m_actions.isEmpty()) {
+ m_selected = (m_selected + 1 + m_actions.count()) % m_actions.count();
+ QItemAnimation *anim = new QItemAnimation(m_selection, QItemAnimation::Position);
+ anim->setEndValue(m_actions.at(m_selected)->pos());
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ }
+ break;
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ if (!m_actions.isEmpty()) {
+ QItemAnimation *anim = new QItemAnimation(m_selection, QItemAnimation::RotationX);
+ anim->setEndValue(m_selection->xRotation() < 180 ? qreal(360) : qreal(0));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ m_actions.at(m_selected)->trigger();
+ hide();
+ }
+ break;
+ default:
+ QGraphicsItem::keyPressEvent(event);
+ }
+}
+
+void Menu::show()
+{
+ QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::Opacity);
+ anim->setEndValue(qreal(1.));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorX);
+ anim->setEndValue(qreal(1));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorY);
+ anim->setEndValue(qreal(1));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ setFocus();
+}
+
+void Menu::hide()
+{
+ QItemAnimation *anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorX);
+ anim->setEndValue(qreal(.1));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorY);
+ anim->setEndValue(qreal(.1));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(this, QItemAnimation::Opacity);
+ anim->setEndValue(qreal(0));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ parentItem()->setFocus();
+}
+
+
+MenuAction::MenuAction(const QString &text, Menu * parent)
+ : QGraphicsTextItem(text,parent)
+{
+ QFont f = font();
+ f.setPointSize(18);
+ setFont(f);
+ setDefaultTextColor(Qt::white);
+}
+
+void MenuAction::trigger()
+{
+ emit triggered();
+}
diff --git a/examples/animation/photobrowser/menu.h b/examples/animation/photobrowser/menu.h
new file mode 100644
index 0000000..9514cfe
--- /dev/null
+++ b/examples/animation/photobrowser/menu.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __MENU__H__
+#define __MENU__H__
+
+#include <QtGui>
+
+class MenuAction;
+
+class Menu : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ Menu(QGraphicsItem *parent);
+ ~Menu();
+
+ MenuAction *addAction(const QString&, QObject *receiver = 0, const char* slot = 0 );
+
+ QRectF boundingRect() const;
+ void keyPressEvent ( QKeyEvent * event );
+public slots:
+ void show();
+ void hide();
+private:
+ QList<MenuAction*> m_actions;
+ QGraphicsRectItem *m_selection;
+ int m_selected;
+};
+
+class MenuAction : public QGraphicsTextItem
+{
+ Q_OBJECT
+public:
+ MenuAction(const QString &text, Menu * parent);
+ void trigger();
+signals:
+ void triggered();
+};
+
+
+#endif //__RIVERITEM__H__
diff --git a/examples/animation/photobrowser/photobrowser.pro b/examples/animation/photobrowser/photobrowser.pro
new file mode 100644
index 0000000..21f03d6
--- /dev/null
+++ b/examples/animation/photobrowser/photobrowser.pro
@@ -0,0 +1,17 @@
+######################################################################
+# Automatically generated by qmake (2.01a) ven. 22. août 13:09:33 2008
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp \
+ river.cpp \
+ riveritem.cpp \
+ menu.cpp
+HEADERS += river.h \
+ riveritem.h \
+ menu.h
diff --git a/examples/animation/photobrowser/river.cpp b/examples/animation/photobrowser/river.cpp
new file mode 100644
index 0000000..f3dd0746
--- /dev/null
+++ b/examples/animation/photobrowser/river.cpp
@@ -0,0 +1,561 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "river.h"
+#include "riveritem.h"
+
+#include "qvariantanimation.h"
+
+#include <QtCore/QDebug>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QGraphicsScene>
+#include <QtGui/QPainter>
+
+
+#define GRID_ROW_COUNT 3
+#define GRID_COLUMN_COUNT 2
+#define GRID_DIMENSIONS (GRID_ROW_COUNT * GRID_COLUMN_COUNT)
+#define ITEM_COUNT 12
+
+#define RIVER_MAGNIFY(ITEM) (qreal(0.50) + (ITEM)->zValue()*2 )
+#define GRID_MAGNIFY qreal(1.5)
+#define GRID_CURRENT_MAGNIFY 2
+
+River::River(const QString &path) :
+m_images(QDir(path).entryInfoList(QStringList() << QLatin1String("*.jpg") << QLatin1String("*.png"))),
+m_currentImage(0), m_mode(RiverMode), m_selectedItem(-1) , m_topLeftIndex(-1)
+{
+ setFocusPolicy(Qt::StrongFocus);
+ setGeometry(QRectF( QPointF(), fixedSize()));
+
+
+ for (int i = 0; i < ITEM_COUNT; ++i) {
+ RiverItem * item = new RiverItem(this);
+
+ //here we also randomize the x position (not when looping)
+ const int x = qrand() % fixedSize().width();
+ item->setPos(x, -1);
+
+ m_items.insert(m_currentImage, item);
+ addUnusedRiverItem(item);
+ }
+
+}
+
+QPointF River::gridItemPosition(int row, int col) const
+{
+ if (col < 0) {
+ col += GRID_COLUMN_COUNT;
+ row --;
+ }
+ return QPointF(rect().width()*(col*2 + 1)/(GRID_COLUMN_COUNT*2),
+ rect().height()*(row*2 + 1)/(GRID_ROW_COUNT*2));
+}
+
+QPixmap River::pixmap(int index) const
+{
+ if (index < 0 || index >= m_images.size())
+ return QPixmap();
+
+ if (m_pixmaps.size() <= index) {
+ m_pixmaps.resize(index+1);
+ }
+
+ if (m_pixmaps.at(index).isNull()) {
+ m_pixmaps[index] = QPixmap(m_images.at(index).absoluteFilePath());
+ }
+
+ return m_pixmaps.at(index);
+}
+
+void River::addUnusedRiverItem(RiverItem * item)
+{
+ if (m_images.isEmpty())
+ return;
+
+ QRectF realItemRect = item->mapToParent(item->boundingRect()).boundingRect();
+
+ int y = item->pos().y();
+ int x = item->pos().x();
+ if (x >= fixedSize().width() || x < -realItemRect.width() || y < 0) {
+ //we set the new pixmap
+
+ m_items.remove(m_items.key(item));
+
+ while (m_items.contains(m_currentImage))
+ m_currentImage = (m_currentImage + 1 ) % m_images.size();
+
+ item->setPixmap(pixmap(m_currentImage));
+
+ m_items.insert(m_currentImage, item);
+ //this manages looping as well
+ m_currentImage = (m_currentImage + 1 ) % m_images.size();
+
+ item->setZValue(qreal(qrand()%100)/200.0);
+
+ QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene());
+ anim->setEndValue(RIVER_MAGNIFY(item));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene());
+ anim->setEndValue(RIVER_MAGNIFY(item));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+
+ realItemRect = item->mapToParent(item->boundingRect()).boundingRect();
+
+ y = -realItemRect.y() + qrand() % (fixedSize().height() - int(realItemRect.height()));
+ if (x >= fixedSize().width()) {
+ x = -realItemRect.width()/2;
+ }
+ }
+
+ item->setPos(x, y);
+
+ const QPointF target(QPointF(fixedSize().width() + realItemRect.width()/2, y));
+
+ const int distance = target.x() - x;
+
+ const int duration = (40 - 50*item->zValue() ) * distance;
+ QItemAnimation *a = new QItemAnimation(item, QItemAnimation::Position, scene());
+ a->setEndValue(target);
+ a->setDuration(duration);
+ a->start(QAbstractAnimation::DeleteWhenStopped);
+ connect(a, SIGNAL(finished()), SLOT(animationFinished()));
+}
+
+void River::animationFinished()
+{
+ QItemAnimation *anim = qobject_cast<QItemAnimation*>(sender());
+ if (!anim || anim->propertyName() != QItemAnimation::Position)
+ return;
+
+ /*RiverItem *item = static_cast<RiverItem*>(anim->graphicsItem());
+ if (m_mode != RiverMode) {*/
+ /*int key = m_items.key(item);
+ if (key < m_topLeftIndex || key >= m_topLeftIndex + GRID_DIMENSIONS) {
+ delete item;
+ m_items.remove(key);
+ }*/
+ //return;
+
+ //}
+
+ addUnusedRiverItem(static_cast<RiverItem*>(anim->targetItem()));
+}
+
+void River::switchPaused()
+{
+ const bool paused = m_pausedAnimations.isEmpty();
+ if (paused)
+ m_pausedAnimations = scene()->findChildren<QItemAnimation*>();
+
+ foreach(QItemAnimation *anim, m_pausedAnimations) {
+ if (paused)
+ anim->pause();
+ else
+ anim->resume();
+ }
+
+ if (!paused)
+ m_pausedAnimations.clear();
+}
+
+void River::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
+{
+ painter->fillRect(option->rect, Qt::black);
+}
+
+void River::setMode(Mode m)
+{
+ if (m_mode == m)
+ return;
+
+ Mode oldMode = m_mode;
+ m_mode = m;
+ switch(m)
+ {
+ case RiverMode:
+ m_mode = oldMode; //some animation may be stopt, and we don't want that animationFinished we were in that mode yet
+ foreach (RiverItem *item, m_items) {
+ const int x = qrand() % fixedSize().width();
+ const int y = qrand() % fixedSize().width();
+ QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene());
+ anim->setEndValue(RIVER_MAGNIFY(item));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene());
+ anim->setEndValue(RIVER_MAGNIFY(item));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(item, QItemAnimation::Position, scene());
+ anim->setEndValue(QPointF(x, y));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ connect(anim, SIGNAL(finished()), SLOT(animationFinished()));
+ }
+ m_mode = m;
+ break;
+
+ case GridMode:
+
+ if (oldMode == GridFullScreenMode) {
+ currentItem()->setFullScreen(false, GRID_CURRENT_MAGNIFY);
+ } else {
+ m_topLeftIndex = -GRID_DIMENSIONS;
+ foreach (RiverItem *item, m_items) {
+ QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene());
+ anim->setEndValue(GRID_MAGNIFY);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene());
+ anim->setEndValue(GRID_MAGNIFY);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ }
+ adjustGrid(m_currentImage - GRID_DIMENSIONS + 1);
+ setCurrentItem(m_topLeftIndex);
+ }
+ break;
+ case GridFullScreenMode:
+ //let's put the current item fullscreen
+ currentItem()->setFullScreen(true, GRID_CURRENT_MAGNIFY);
+ break;
+ case CoverMode:
+ m_gridItem = m_items.values();
+ setCurrentItem(m_gridItem.count()/2);
+ default:
+ break;
+ }
+}
+
+River::Mode River::mode() const
+{
+ return m_mode;
+}
+
+QSize River::fixedSize()
+{
+ return QSize(352, 416);
+}
+
+//the name of this method is not that good...
+void River::makeCenterAvailable(qreal size)
+{
+ QRectF center(QPointF(), QSizeF(size, size));
+ center.moveCenter(rect().center());
+
+ const QList<QGraphicsItem*> list = scene()->items(center);
+
+ foreach(QGraphicsItem *item, m_items) {
+
+ if (!list.contains(item))
+ continue;
+
+ QPointF pos = item->pos();
+
+ if (pos.y() < rect().center().y()) {
+ //item is above center
+ pos.ry() = center.top() - item->boundingRect().height() - 1;
+ } else {
+ //item is below the center
+ pos.ry() = center.bottom() + 1;
+ }
+ QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::Position, scene());
+ anim->setEndValue(pos);
+ anim->setDuration(150);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ }
+}
+
+
+//this is there just to test small interaction
+void River::keyPressEvent ( QKeyEvent * keyEvent )
+{
+ switch(keyEvent->key())
+ {
+ case Qt::Key_O:
+ {
+ QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::Opacity, scene());
+ anim->setDuration(2000);
+ anim->setEndValue(qreal(.5));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ }
+ break;
+ case Qt::Key_N:
+ //that's a test
+ makeCenterAvailable(60);
+ break;
+ case Qt::Key_P:
+ switchPaused();
+ break;
+ case Qt::Key_V:
+ setMode(GridMode);
+ break;
+ case Qt::Key_R:
+ setMode(RiverMode);
+ break;
+ case Qt::Key_C:
+ setMode(CoverMode);
+ break;
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ if (m_mode == RiverMode) {
+ setMode(GridMode);
+ } else if (m_mode == GridMode) {
+ setMode(GridFullScreenMode);
+ } else if (m_mode == GridFullScreenMode) {
+ setMode(GridMode);
+ }
+ break;
+ case Qt::Key_Escape:
+ if (m_mode == GridFullScreenMode) {
+ setMode(GridMode);
+ } else if (m_mode == GridMode || m_mode == CoverMode) {
+ setMode(RiverMode);
+ } else if (m_mode == RiverMode) {
+ menu->show();
+ }
+ break;
+ case Qt::Key_Right:
+ if (m_mode == GridMode) {
+ navigateBy(+1);
+ } else if (m_mode == CoverMode) {
+ setCurrentItem(m_selectedItem + 1);
+ }
+ break;
+ case Qt::Key_Left:
+ if (m_mode == GridMode) {
+ navigateBy(-1);
+ } else if (m_mode == CoverMode) {
+ setCurrentItem(m_selectedItem - 1);
+ }
+ break;
+ case Qt::Key_Down:
+ if (m_mode == GridMode) {
+ navigateBy(GRID_COLUMN_COUNT);
+ }
+ break;
+ case Qt::Key_Up:
+ if (m_mode == GridMode) {
+ navigateBy(-GRID_COLUMN_COUNT);
+ }
+ break;
+// case Qt::Key_PageUp:
+ case Qt::Key_M:
+ menu->show();
+ break;
+ case Qt::Key_Space:
+ if (m_mode == GridMode) {
+ RiverItem *item = currentItem();
+ if(!item)
+ break;
+
+ //stupid sequence.
+ QPointF pos = item->pos();
+ QAnimationGroup *group = new QSequentialAnimationGroup();
+ //item->animator()->beginSequence();
+
+ QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::Position, scene());
+ anim->setEndValue(pos);
+ group->addAnimation(anim);
+ anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene());
+ anim->setEndValue(qreal(1.));
+ anim->setDuration(500);
+ group->addAnimation(anim);
+ anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene());
+ anim->setEndValue(qreal(1.));
+ anim->setDuration(500);
+ group->addAnimation(anim);
+ anim = new QItemAnimation(item, QItemAnimation::RotationX, scene());
+ anim->setEndValue(qreal(0));
+ group->addAnimation(anim);
+ group->start(QAbstractAnimation::DeleteWhenStopped);
+ }
+ default:
+ break;
+ }
+
+ QGraphicsItem::keyPressEvent(keyEvent);
+}
+
+
+void River::setGridMode()
+{
+ setMode(GridMode);
+}
+
+void River::setRiverMode()
+{
+ setMode(RiverMode);
+}
+
+void River::setCoverMode()
+{
+ setMode(CoverMode);
+}
+
+
+void River::adjustGrid(int newTopLeft)
+{
+ for (int i = newTopLeft ; i < newTopLeft + GRID_DIMENSIONS; i++) {
+ if (!m_items.contains(i)) {
+ RiverItem *item = createItem(i);
+ int row = (i - m_topLeftIndex) / GRID_COLUMN_COUNT;
+ int col = (i - m_topLeftIndex) % GRID_COLUMN_COUNT;
+ item->setPos(gridItemPosition(row, col));
+ item->setXScale(0);
+ item->setYScale(0);
+ QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene());
+ anim->setEndValue(GRID_MAGNIFY);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene());
+ anim->setEndValue(GRID_MAGNIFY);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ }
+ }
+ newTopLeft = newTopLeft - newTopLeft % GRID_COLUMN_COUNT;
+
+ QHash<int, RiverItem *>::iterator it = m_items.begin();
+ while (it != m_items.constEnd()) {
+ const int imageIdx = it.key();
+ RiverItem *item = *it;
+ QSizeF itemSize = item->boundingRect().size();
+ if ((imageIdx >= newTopLeft && imageIdx < newTopLeft + GRID_DIMENSIONS)
+ || boundingRect().adjusted(-itemSize.width()/2, -itemSize.height()/2, itemSize.width()/2, itemSize.height()/2)
+ .contains(item->pos())) {
+ int row = (imageIdx-newTopLeft) / GRID_COLUMN_COUNT;
+ int col = (imageIdx-newTopLeft) % GRID_COLUMN_COUNT;
+ QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::Position, scene());
+ anim->setEndValue(gridItemPosition(row, col));
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ ++it;
+ } else {
+ ++it; /* ### ideally we should remove the items, but this cause the photobrowser to crash
+ because the QItemAnimations are not notified the item is deleted
+ delete item;
+ it = m_items.erase(it);
+ */
+ }
+ }
+
+ m_topLeftIndex = newTopLeft;
+}
+
+
+RiverItem *River::createItem(int imageIndex)
+{
+ Q_ASSERT(!m_items.contains(imageIndex));
+ RiverItem * item = new RiverItem(this);
+ item->setPixmap(pixmap(imageIndex));
+ m_items.insert(imageIndex,item);
+ return item;
+}
+
+void River::setCurrentItem(int newCurrentItem)
+{
+ if (m_mode == CoverMode)
+ {
+ m_selectedItem = newCurrentItem;
+ for (int i = 0; i < m_gridItem.count(); i++) {
+ QVariantAnimation *anim;
+ RiverItem *item = m_gridItem.at(i);
+
+ qreal rotation = 0;
+ qreal width = boundingRect().width() / 2;
+ qreal x = width;
+ qreal scale = 3;
+ qreal z = 1;
+ qreal y = boundingRect().height()/2;
+
+ if (i < newCurrentItem - 4) {
+ item->setVisible(false);
+ item->setPos(QPointF(0, y));
+ continue;
+ } else if(i > newCurrentItem + 4) {
+ item->setVisible(false);
+ item->setPos(QPointF(boundingRect().width(), y));
+ continue;
+ } else if (i < newCurrentItem) {
+ x = (i - newCurrentItem + 4) * width/7;
+ rotation = -75;
+ scale = 2;
+ z = 1.+qreal(i-newCurrentItem)/10.;
+ } else if (i > newCurrentItem) {
+ x = width + (i - newCurrentItem + 3) * width/7;
+ rotation = 75;
+ scale = 2;
+ z = 1.-qreal(i-newCurrentItem)/8.;
+ }
+
+ item->setVisible(true);
+ item->setZValue(z);
+
+ anim = new QItemAnimation(item, QItemAnimation::RotationY, scene());
+ anim->setEndValue(rotation);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+
+ anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene());
+ anim->setEndValue(scale);
+ anim->start(QVariantAnimation::DeleteWhenStopped);
+
+ anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene());
+ anim->setEndValue(scale);
+ anim->start(QVariantAnimation::DeleteWhenStopped);
+
+ anim = new QItemAnimation(item, QItemAnimation::Position, scene());
+ anim->setEndValue(QPointF(x,y));
+ anim->start(QVariantAnimation::DeleteWhenStopped);
+ }
+ return;
+ }
+
+
+ //deselect the current item
+ if (m_selectedItem >= 0 && m_items.contains(m_selectedItem)) {
+ RiverItem *item = m_items.value(m_selectedItem);
+ item->setZValue(qreal(qrand()%100)/200.0);
+ QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene());
+ anim->setEndValue(GRID_MAGNIFY);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene());
+ anim->setEndValue(GRID_MAGNIFY);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ }
+
+ if (newCurrentItem < 0) {
+ m_selectedItem = newCurrentItem;
+ return;
+ }
+
+ //ensure visible;
+ if (newCurrentItem < m_topLeftIndex) {
+ adjustGrid(newCurrentItem);
+ } else if (newCurrentItem >= m_topLeftIndex + GRID_DIMENSIONS) {
+ adjustGrid(newCurrentItem - GRID_DIMENSIONS + GRID_COLUMN_COUNT);
+ }
+
+ //select the new one
+ m_selectedItem = newCurrentItem;
+ RiverItem *item = currentItem();
+ Q_ASSERT(item);
+ item->setZValue(1);
+
+ QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene());
+ anim->setEndValue(GRID_CURRENT_MAGNIFY);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+ anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene());
+ anim->setEndValue(GRID_CURRENT_MAGNIFY);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
+void River::navigateBy(int offset)
+{
+ int newSelection = m_selectedItem + offset;
+ const int imageCount = m_images.size();
+ while (newSelection < 0)
+ newSelection += imageCount;
+ newSelection %= imageCount;
+ setCurrentItem(newSelection);
+}
diff --git a/examples/animation/photobrowser/river.h b/examples/animation/photobrowser/river.h
new file mode 100644
index 0000000..25bf62a
--- /dev/null
+++ b/examples/animation/photobrowser/river.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __RIVER__H__
+#define __RIVER__H__
+
+#include <QtCore/QDirIterator>
+#include <QtGui/QGraphicsWidget>
+
+#include "menu.h"
+
+class RiverItem;
+
+class River : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ enum Mode
+ {
+ RiverMode,
+ GridMode,
+ GridFullScreenMode,
+ CoverMode
+ };
+
+ River(const QString &path);
+ void addUnusedRiverItem(RiverItem * item);
+
+ static QSize fixedSize();
+
+ void switchPaused();
+
+ void setMode(Mode m);
+ Mode mode() const;
+
+ Menu *menu;
+
+protected:
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ void keyPressEvent ( QKeyEvent * keyEvent );
+ void makeCenterAvailable(qreal size);
+ QPointF gridItemPosition(int row, int col) const;
+ QPixmap pixmap(int index) const;
+
+protected slots:
+ void animationFinished();
+public slots:
+ void setRiverMode();
+ void setGridMode();
+ void setCoverMode();
+
+private:
+ const QFileInfoList m_images;
+ int m_currentImage;
+ mutable QVector<QPixmap> m_pixmaps;
+ QHash<int, RiverItem*> m_items;
+ QList<RiverItem*> m_gridItem;
+ QList<QItemAnimation*> m_pausedAnimations;
+ Mode m_mode;
+
+ void adjustGrid(int topRight);
+ RiverItem *currentItem() { return m_items.value(m_selectedItem); }
+ RiverItem *createItem(int imageIndex);
+ void setCurrentItem(int currentItem);
+ void navigateBy(int offset);
+
+ int m_selectedItem;
+ int m_topLeftIndex;
+
+};
+
+
+#endif //__RIVERITEM__H__
diff --git a/examples/animation/photobrowser/riveritem.cpp b/examples/animation/photobrowser/riveritem.cpp
new file mode 100644
index 0000000..f6523a7
--- /dev/null
+++ b/examples/animation/photobrowser/riveritem.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "riveritem.h"
+#include "river.h"
+
+RiverItem::RiverItem(QGraphicsItem *parent) : QGraphicsPixmapItem(parent), m_fullscreen(false)
+{
+ setCacheMode(DeviceCoordinateCache);
+}
+
+RiverItem::~RiverItem()
+{
+}
+
+void RiverItem::setPixmap(const QPixmap &pix)
+{
+ const QSize oldSize = pixmap().size();
+ const QSize newSize = pix.size();
+ QGraphicsPixmapItem::setPixmap(pix);
+
+ if (newSize != oldSize) {
+ setOffset(-newSize.width()/2, -newSize.height()/2);
+ const qreal scaleFactor = qreal(River::fixedSize().height())/(qreal(pix.height()*7));
+ setTransform(QTransform().scale(scaleFactor, scaleFactor));
+ prepareGeometryChange();
+ }
+}
+
+
+void RiverItem::setFullScreen(bool b, qreal originScaleFactor)
+{
+ if (m_fullscreen == b)
+ return;
+
+ m_fullscreen = b;
+
+ QPointF newPos;
+ qreal rotationZ;
+ qreal scaleX, scaleY;
+
+ if (b) {
+ const QSizeF basePixmapSize = transform().map(boundingRect()).boundingRect().size();
+
+ newPos = parentItem()->boundingRect().center();
+ rotationZ = 90;
+ scaleY = qreal(River::fixedSize().width()) / basePixmapSize.height() * yScale();
+ scaleX = qreal(River::fixedSize().height()) / basePixmapSize.width() * xScale();
+
+ if (m_nonFSPos.isNull()) {
+ m_nonFSPos = pos(); //let's save our current (non fullscreen) position
+ }
+
+ } else {
+ Q_ASSERT(!m_nonFSPos.isNull());
+ rotationZ = 0;
+ scaleX = originScaleFactor;
+ scaleY = originScaleFactor;
+ newPos = m_nonFSPos;
+ }
+
+ QAnimationGroup *group = new QParallelAnimationGroup(scene());
+ QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::Position);
+ anim->setEndValue(newPos);
+ group->addAnimation(anim);
+ anim = new QItemAnimation(this, QItemAnimation::RotationZ);
+ anim->setEndValue(rotationZ);
+ group->addAnimation(anim);
+ anim = new QItemAnimation(this, QItemAnimation::ScaleFactorX);
+ anim->setEndValue(scaleX);
+ group->addAnimation(anim);
+ anim = new QItemAnimation(this, QItemAnimation::ScaleFactorY);
+ anim->setEndValue(scaleY);
+ group->addAnimation(anim);
+ group->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
+void RiverItem::mousePressEvent(QGraphicsSceneMouseEvent*)
+{
+ //just let it rotate on itself
+ QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::RotationY);
+ anim->setEndValue(yRotation() < 180 ? 360 : 0);
+ anim->setDuration(500);
+ anim->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
+
diff --git a/examples/animation/photobrowser/riveritem.h b/examples/animation/photobrowser/riveritem.h
new file mode 100644
index 0000000..39fdcc2
--- /dev/null
+++ b/examples/animation/photobrowser/riveritem.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __RIVERITEM__H__
+#define __RIVERITEM__H__
+
+#include <QtGui/QGraphicsPixmapItem>
+
+class RiverItemAnimator;
+
+class RiverItem : public QGraphicsPixmapItem
+{
+public:
+ RiverItem(QGraphicsItem *parent);
+ ~RiverItem();
+
+ void setPixmap(const QPixmap &);
+ void setFullScreen(bool b, qreal originScaleFactor);
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent*);
+
+private:
+ QPointF m_nonFSPos; //to save the position when not in fullscreen
+ bool m_fullscreen;
+};
+
+#endif //__RIVERITEM__H__
diff --git a/examples/animation/piemenu/main.cpp b/examples/animation/piemenu/main.cpp
new file mode 100644
index 0000000..28f62d0
--- /dev/null
+++ b/examples/animation/piemenu/main.cpp
@@ -0,0 +1,26 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include "scene.h"
+#include "qgraphicspiemenu.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ Scene scene;
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/animation/piemenu/piemenu.pro b/examples/animation/piemenu/piemenu.pro
new file mode 100644
index 0000000..4d7a067
--- /dev/null
+++ b/examples/animation/piemenu/piemenu.pro
@@ -0,0 +1,8 @@
+SOURCES += \
+ main.cpp \
+ qgraphicspiemenu.cpp \
+ scene.cpp
+HEADERS += \
+ qgraphicspiemenu.h \
+ qgraphicspiemenu_p.h \
+ scene.h
diff --git a/examples/animation/piemenu/qgraphicspiemenu.cpp b/examples/animation/piemenu/qgraphicspiemenu.cpp
new file mode 100644
index 0000000..c913423
--- /dev/null
+++ b/examples/animation/piemenu/qgraphicspiemenu.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qgraphicspiemenu.h"
+#include "qgraphicspiemenu_p.h"
+
+#include <QtGui/qaction.h>
+
+QGraphicsPieMenu::QGraphicsPieMenu(QGraphicsItem *parent)
+ : QGraphicsWidget(parent), d_ptr(new QGraphicsPieMenuPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->machine = new QStateMachine();
+ d_ptr->popupState = new QState(d_ptr->machine->rootState());
+ d_ptr->machine->setInitialState(d_ptr->popupState);
+ d_ptr->menuAction = new QAction(this);
+}
+
+QGraphicsPieMenu::QGraphicsPieMenu(const QString &title, QGraphicsItem *parent)
+ : QGraphicsWidget(parent), d_ptr(new QGraphicsPieMenuPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->machine = new QStateMachine();
+ d_ptr->popupState = new QState(d_ptr->machine->rootState());
+ d_ptr->machine->setInitialState(d_ptr->popupState);
+ d_ptr->menuAction = new QAction(this);
+ setTitle(title);
+}
+
+QGraphicsPieMenu::QGraphicsPieMenu(const QIcon &icon, const QString &title, QGraphicsItem *parent)
+ : QGraphicsWidget(parent), d_ptr(new QGraphicsPieMenuPrivate)
+{
+ d_ptr->q_ptr = this;
+ d_ptr->machine = new QStateMachine();
+ d_ptr->popupState = new QState(d_ptr->machine->rootState());
+ d_ptr->machine->setInitialState(d_ptr->popupState);
+ d_ptr->menuAction = new QAction(this);
+ setIcon(icon);
+ setTitle(title);
+}
+
+QGraphicsPieMenu::~QGraphicsPieMenu()
+{
+ delete d_ptr;
+}
+
+QAction *QGraphicsPieMenu::addAction(const QString &text)
+{
+ QAction *action = new QAction(text, this);
+ addAction(action);
+ return action;
+}
+
+QAction *QGraphicsPieMenu::addAction(const QIcon &icon, const QString &text)
+{
+ QAction *action = new QAction(icon, text, this);
+ addAction(action);
+ return action;
+}
+
+QAction *QGraphicsPieMenu::addAction(const QString &text, const QObject *receiver, const char *member, const QKeySequence &shortcut)
+{
+ QAction *action = new QAction(text, this);
+ action->setShortcut(shortcut);
+ connect(action, SIGNAL(triggered(bool)), receiver, member);
+ addAction(action);
+ return action;
+}
+
+QAction *QGraphicsPieMenu::addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char *member, const QKeySequence &shortcut)
+{
+ QAction *action = new QAction(icon, text, this);
+ action->setShortcut(shortcut);
+ connect(action, SIGNAL(triggered(bool)), receiver, member);
+ addAction(action);
+ return action;
+}
+
+QAction *QGraphicsPieMenu::addMenu(QGraphicsPieMenu *menu)
+{
+ QAction *action = menu->menuAction();
+ addAction(action);
+ return action;
+}
+
+QGraphicsPieMenu *QGraphicsPieMenu::addMenu(const QString &title)
+{
+ QGraphicsPieMenu *menu = new QGraphicsPieMenu(title, this);
+ addMenu(menu);
+ return menu;
+}
+
+QGraphicsPieMenu *QGraphicsPieMenu::addMenu(const QIcon &icon, const QString &title)
+{
+ QGraphicsPieMenu *menu = new QGraphicsPieMenu(icon, title, this);
+ addMenu(menu);
+ return menu;
+}
+
+QAction *QGraphicsPieMenu::addSeparator()
+{
+ QAction *action = new QAction(this);
+ action->setSeparator(true);
+ addAction(action);
+ return action;
+}
+
+QAction *QGraphicsPieMenu::insertMenu(QAction *before, QGraphicsPieMenu *menu)
+{
+ QAction *action = menu->menuAction();
+ insertAction(before, action);
+ return action;
+}
+
+QAction *QGraphicsPieMenu::insertSeparator(QAction *before)
+{
+ QAction *action = new QAction(this);
+ action->setSeparator(true);
+ insertAction(before, action);
+ return action;
+}
+
+QAction *QGraphicsPieMenu::menuAction() const
+{
+ return d_func()->menuAction;
+}
+
+bool QGraphicsPieMenu::isEmpty() const
+{
+ // ### d->actions
+ QList<QAction *> actionList = actions();
+ bool ret = true;
+ for (int i = 0; ret && i < actionList.size(); ++i) {
+ const QAction *action = actionList.at(i);
+ if (!action->isSeparator() && action->isVisible()) {
+ ret = false;
+ break;
+ }
+ }
+ return ret;
+}
+
+void QGraphicsPieMenu::clear()
+{
+ // ### d->actions
+ QList<QAction *> actionList = actions();
+ for(int i = 0; i < actionList.size(); i++) {
+ QAction *action = actionList.at(i);
+ removeAction(action);
+ if (action->parent() == this && action->associatedGraphicsWidgets().isEmpty())
+ delete action;
+ }
+}
+
+void QGraphicsPieMenu::popup(const QPointF &pos)
+{
+ Q_UNUSED(pos);
+ Q_D(QGraphicsPieMenu);
+ d->machine->start();
+}
+
+QAction *QGraphicsPieMenu::exec()
+{
+ return exec(pos());
+}
+
+QAction *QGraphicsPieMenu::exec(const QPointF &pos)
+{
+ Q_UNUSED(pos);
+ return 0;
+}
+
+QAction *QGraphicsPieMenu::exec(QList<QAction *> actions, const QPointF &pos)
+{
+ QGraphicsPieMenu menu;
+ for (QList<QAction *>::ConstIterator it = actions.constBegin(); it != actions.constEnd(); ++it)
+ menu.addAction(*it);
+ return menu.exec(pos);
+}
+
+QString QGraphicsPieMenu::title() const
+{
+ Q_D(const QGraphicsPieMenu);
+ return d->title;
+}
+
+void QGraphicsPieMenu::setTitle(const QString &title)
+{
+ Q_D(QGraphicsPieMenu);
+ d->title = title;
+ updateGeometry();
+}
+
+QIcon QGraphicsPieMenu::icon() const
+{
+ Q_D(const QGraphicsPieMenu);
+ return d->icon;
+}
+
+void QGraphicsPieMenu::setIcon(const QIcon &icon)
+{
+ Q_D(QGraphicsPieMenu);
+ d->icon = icon;
+ updateGeometry();
+}
+
+QSizeF QGraphicsPieMenu::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED(which);
+ Q_UNUSED(constraint);
+ return QSizeF(1, 1);
+}
diff --git a/examples/animation/piemenu/qgraphicspiemenu.h b/examples/animation/piemenu/qgraphicspiemenu.h
new file mode 100644
index 0000000..68b4ba9
--- /dev/null
+++ b/examples/animation/piemenu/qgraphicspiemenu.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSPIEMENU_H
+#define QGRAPHICSPIEMENU_H
+
+#include <QtGui/qgraphicswidget.h>
+
+class QGraphicsPieMenuPrivate;
+class QGraphicsPieMenu : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ QGraphicsPieMenu(QGraphicsItem *parent = 0);
+ QGraphicsPieMenu(const QString &title, QGraphicsItem *parent = 0);
+ QGraphicsPieMenu(const QIcon &icon, const QString &title, QGraphicsItem *parent = 0);
+ ~QGraphicsPieMenu();
+
+#ifdef Q_NO_USING_KEYWORD
+ inline void addAction(QAction *action) { QGraphicsWidget::addAction(action); }
+#else
+ using QGraphicsWidget::addAction;
+#endif
+ QAction *addAction(const QString &text);
+ QAction *addAction(const QIcon &icon, const QString &text);
+ QAction *addAction(const QString &text, const QObject *receiver, const char *member, const QKeySequence &shortcut = 0);
+ QAction *addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char *member, const QKeySequence &shortcut = 0);
+ QAction *addMenu(QGraphicsPieMenu *menu);
+ QGraphicsPieMenu *addMenu(const QString &title);
+ QGraphicsPieMenu *addMenu(const QIcon &icon, const QString &title);
+ QAction *addSeparator();
+ QAction *insertMenu(QAction *before, QGraphicsPieMenu *menu);
+ QAction *insertSeparator(QAction *before);
+
+ QAction *menuAction() const;
+
+ bool isEmpty() const;
+ void clear();
+
+ void popup(const QPointF &pos);
+ QAction *exec();
+ QAction *exec(const QPointF &pos);
+ static QAction *exec(QList<QAction *> actions, const QPointF &pos);
+
+ QString title() const;
+ void setTitle(const QString &title);
+
+ QIcon icon() const;
+ void setIcon(const QIcon &icon);
+
+Q_SIGNALS:
+ void aboutToShow();
+ void aboutToHide();
+ void triggered(QAction *action);
+ void hovered(QAction *action);
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+
+private:
+ Q_DISABLE_COPY(QGraphicsPieMenu)
+ Q_DECLARE_PRIVATE(QGraphicsPieMenu)
+ QGraphicsPieMenuPrivate *d_ptr;
+};
+
+#endif
diff --git a/examples/animation/piemenu/qgraphicspiemenu_p.h b/examples/animation/piemenu/qgraphicspiemenu_p.h
new file mode 100644
index 0000000..87a749c
--- /dev/null
+++ b/examples/animation/piemenu/qgraphicspiemenu_p.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSPIEMENU_P_H
+#define QGRAPHICSPIEMENU_P_H
+
+#include "qgraphicspiemenu.h"
+#include "qgraphicspiemenusection_p.h"
+
+#include <QtGui/qicon.h>
+#include <QtCore/qstate.h>
+#include <QtCore/qtransition.h>
+#include <QtCore/qstatemachine.h>
+
+class QAction;
+class QEventLoop;
+class QGraphicsPieMenuSection;
+
+class QGraphicsPieMenuPrivate
+{
+ Q_DECLARE_PUBLIC(QGraphicsPieMenu);
+public:
+ void init(const QIcon &icon = QIcon(), const QString &title = QString());
+
+ QIcon icon;
+ QString title;
+ QStateMachine *machine;
+ QState *popupState;
+ //QTransition *transition;
+ QList<QGraphicsPieMenuSection *> sections;
+
+ QEventLoop *eventLoop;
+
+ QAction *menuAction;
+ QGraphicsPieMenu *q_ptr;
+
+ void updatePopupState();
+};
+
+#endif
diff --git a/examples/animation/piemenu/qgraphicspiemenusection_p.h b/examples/animation/piemenu/qgraphicspiemenusection_p.h
new file mode 100644
index 0000000..328f742
--- /dev/null
+++ b/examples/animation/piemenu/qgraphicspiemenusection_p.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSPIEMENUSECTION_H
+#define QGRAPHICSPIEMENUSECTION_H
+
+#include <QtGui/qgraphicswidget.h>
+#include <QtGui/qpainter.h>
+
+class QGraphicsPieMenuSection : public QGraphicsWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation)
+public:
+ QGraphicsPieMenuSection(QGraphicsItem *parent = 0)
+ : QGraphicsWidget(parent), rot(0)
+ { }
+
+ qreal rotation() const
+ {
+ return rot;
+ }
+ void setRotation(qreal rotation)
+ {
+ rot = rotation;
+ setTransform(QTransform().rotate(rot));
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->setPen(QPen(Qt::black, 1));
+ painter->setBrush(QBrush(Qt::gray));
+ painter->drawPie(QRectF(-100, -100, 200, 200), 0, -30 * 16);
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &size = QSizeF()) const
+ {
+ Q_UNUSED(which);
+ Q_UNUSED(size);
+ return QSizeF(100, 30);
+ }
+
+private:
+ qreal rot;
+};
+
+#endif
diff --git a/examples/animation/piemenu/scene.cpp b/examples/animation/piemenu/scene.cpp
new file mode 100644
index 0000000..08aad06
--- /dev/null
+++ b/examples/animation/piemenu/scene.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qgraphicspiemenu.h"
+#include "scene.h"
+
+#include <QtGui/qaction.h>
+#include <QtGui/qgraphicssceneevent.h>
+
+Scene::Scene(qreal x, qreal y, qreal width, qreal height, QObject *parent)
+ : QGraphicsScene(x, y, width, height, parent)
+{
+}
+
+Scene::Scene(const QRectF &sceneRect, QObject *parent)
+ : QGraphicsScene(sceneRect, parent)
+{
+}
+
+Scene::Scene(QObject *parent)
+ : QGraphicsScene(parent)
+{
+}
+
+Scene::~Scene()
+{
+}
+
+void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ QGraphicsPieMenu *menu = new QGraphicsPieMenu;
+ for (int i = 0; i < 5; ++i)
+ menu->addAction(new QAction(QString("Item %1").arg(i), menu));
+ menu->popup(event->scenePos());
+}
diff --git a/examples/animation/piemenu/scene.h b/examples/animation/piemenu/scene.h
new file mode 100644
index 0000000..676f55f
--- /dev/null
+++ b/examples/animation/piemenu/scene.h
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SCENE_H
+#define SCENE_H
+
+#include <QtGui/qgraphicsscene.h>
+
+class Scene : public QGraphicsScene
+{
+ Q_OBJECT
+public:
+ Scene(qreal x, qreal y, qreal width, qreal height, QObject *parent = 0);
+ Scene(const QRectF &sceneRect, QObject *parent = 0);
+ Scene(QObject *parent = 0);
+ ~Scene();
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+};
+
+#endif
diff --git a/examples/animation/research/memberfunctions/main.cpp b/examples/animation/research/memberfunctions/main.cpp
new file mode 100644
index 0000000..9142f29
--- /dev/null
+++ b/examples/animation/research/memberfunctions/main.cpp
@@ -0,0 +1,48 @@
+#include <QtGui>
+#include "qvalueanimation.h"
+
+AbstractProperty *qGraphicsItemProperty(QGraphicsItem *item, const char *property)
+{
+ if (qstrcmp(property, "pos") == 0) {
+ return new MemberFunctionProperty<QGraphicsItem, QPointF>(item, &QGraphicsItem::pos, &QGraphicsItem::setPos);
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsItem *item = new QGraphicsRectItem(QRectF(0,0, 200, 100));
+ scene.addItem(item);
+
+ QValueAnimation *posAnim = new QValueAnimation;
+ posAnim->setStartValue(QPointF(0,0));
+ posAnim->setEndValue(QPointF(400, 0));
+ posAnim->setDuration(1000);
+ // Alternative 1
+ //posAnim->setMemberFunction(item, &QGraphicsItem::pos, &QGraphicsItem::setPos);
+
+ // Alternative 2
+ //posAnim->setProperty(qMemberFunctionProperty(item, &QGraphicsItem::pos, &QGraphicsItem::setPos));
+
+ // Alternative 3
+ posAnim->setProperty(qGraphicsItemProperty(item, "pos"));
+
+ // Alternative 4, (by implementing the qGraphicsItemProperty QGraphicsItem::property())
+ //posAnim->setProperty(item->property("pos"));
+
+ // can also do this, which abstracts away the whole property thing.
+ // i.e. this interface can also be used for QObject-properties:
+ //posAnim->setAnimationProperty(animationProperty);
+
+ posAnim->start();
+
+ view.resize(800,600);
+ view.show();
+ return app.exec();
+}
+
diff --git a/examples/animation/research/memberfunctions/memberfunctions.pro b/examples/animation/research/memberfunctions/memberfunctions.pro
new file mode 100644
index 0000000..6b67895
--- /dev/null
+++ b/examples/animation/research/memberfunctions/memberfunctions.pro
@@ -0,0 +1,16 @@
+######################################################################
+# Automatically generated by qmake (2.01a) fr 26. sep 13:21:57 2008
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp \
+ qvalueanimation.cpp
+HEADERS += qvalueanimation.h
+
+CONFIG += console
+
diff --git a/examples/animation/research/memberfunctions/qvalueanimation.cpp b/examples/animation/research/memberfunctions/qvalueanimation.cpp
new file mode 100644
index 0000000..2fe9be9
--- /dev/null
+++ b/examples/animation/research/memberfunctions/qvalueanimation.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+
+
+#include "qvalueanimation.h"
+#include "qvalueanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+void QValueAnimationPrivate::initDefaultStartValue()
+{
+ Q_Q(QValueAnimation);
+ if (animProp && !q->startValue().isValid()
+ && ((currentTime == 0 && (currentIteration || currentIteration == 0))
+ || (currentTime == duration && currentIteration == (iterationCount - 1)))) {
+ setDefaultStartValue(animProp->read());
+ }
+}
+
+
+QValueAnimation::QValueAnimation(QObject *parent) : QVariantAnimation(*new QValueAnimationPrivate, parent)
+{
+}
+
+QValueAnimation::~QValueAnimation()
+{
+}
+
+void QValueAnimation::setProperty(AbstractProperty *animProp)
+{
+ Q_D(QValueAnimation);
+ d->animProp = animProp;
+}
+
+/*!
+ \reimp
+ */
+void QValueAnimation::updateCurrentValue(const QVariant &value)
+{
+ Q_D(QValueAnimation);
+ if (state() == QAbstractAnimation::Stopped)
+ return;
+
+ d->animProp->write(value);
+}
+
+
+/*!
+ \reimp
+*/
+void QValueAnimation::updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState)
+{
+ Q_D(QValueAnimation);
+ // Initialize start value
+ if (oldState == QAbstractAnimation::Stopped && newState == QAbstractAnimation::Running)
+ d->initDefaultStartValue();
+}
+
+
+
+#include "moc_qvalueanimation.cpp"
+
+QT_END_NAMESPACE
diff --git a/examples/animation/research/memberfunctions/qvalueanimation.h b/examples/animation/research/memberfunctions/qvalueanimation.h
new file mode 100644
index 0000000..a4aa213
--- /dev/null
+++ b/examples/animation/research/memberfunctions/qvalueanimation.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVALUEANIMATION_H
+#define QVALUEANIMATION_H
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qvariantanimation.h"
+#else
+# include <QtCore/qvariantanimation.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsItem;
+class QValueAnimationPrivate;
+
+QT_MODULE(Gui)
+
+struct AbstractProperty {
+ virtual void write(const QVariant &value) = 0;
+ virtual QVariant read() const = 0;
+};
+
+# define CALL_MEMBER_FN(object,ptrToMember) ((object)->*(ptrToMember))
+template <typename Target, typename T>
+class MemberFunctionProperty : public AbstractProperty {
+public:
+ typedef void (Target::*RefWrite)(const T &);
+ typedef T (Target::*ValRead)(void) const;
+
+ MemberFunctionProperty(Target *target, ValRead readFunc, RefWrite writeFunc)
+ : m_target(target), m_readFn(readFunc), m_writeFn(writeFunc) {}
+
+ virtual void write(const QVariant &value) {
+ CALL_MEMBER_FN(m_target, m_writeFn)(qVariantValue<T>(value));
+ }
+
+ virtual QVariant read() const {
+ if (m_readFn)
+ return qVariantFromValue<T>(CALL_MEMBER_FN(m_target, m_readFn)());
+ return QVariant();
+ }
+
+private:
+ Target *m_target;
+ ValRead m_readFn;
+ RefWrite m_writeFn;
+};
+
+
+class QValueAnimation : public QVariantAnimation
+{
+ Q_OBJECT
+
+public:
+ QValueAnimation(QObject *parent = 0);
+ ~QValueAnimation();
+
+ template <typename Target, typename T>
+ void setMemberFunction(Target *target,
+ T (Target::*readFunc)(void) const, // ### useValRead typedef
+ void (Target::*writeFunc)(const T &) // ### use RefWrite typedef
+ ) {
+ // ### ownership of MemberFunctionProperty
+ AbstractProperty *animProp = new MemberFunctionProperty<Target, T>(target, readFunc, writeFunc);
+ setProperty(animProp);
+ }
+
+ void updateCurrentValue(const QVariant &value);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void setProperty(AbstractProperty *animProp);
+
+private:
+ Q_DISABLE_COPY(QValueAnimation);
+ Q_DECLARE_PRIVATE(QValueAnimation);
+};
+
+#endif // QVALUEANIMATION_H
diff --git a/examples/animation/research/memberfunctions/qvalueanimation_p.h b/examples/animation/research/memberfunctions/qvalueanimation_p.h
new file mode 100644
index 0000000..e6e7682
--- /dev/null
+++ b/examples/animation/research/memberfunctions/qvalueanimation_p.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVALUEANIMATION_P_H
+#define QVALUEANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qvariantanimation_p.h> //###
+
+QT_BEGIN_NAMESPACE
+
+class QValueAnimationPrivate : public QVariantAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QValueAnimation)
+public:
+ QValueAnimationPrivate() : QVariantAnimationPrivate(), animProp(0)
+ {
+ }
+
+ void initDefaultStartValue();
+
+ AbstractProperty *animProp;
+
+ //###TODO
+};
+
+QT_END_NAMESPACE
+
+#endif //QVALUEANIMATION_P_H
diff --git a/examples/animation/research/propertytransform/main.cpp b/examples/animation/research/propertytransform/main.cpp
new file mode 100644
index 0000000..80002c9
--- /dev/null
+++ b/examples/animation/research/propertytransform/main.cpp
@@ -0,0 +1,47 @@
+#include <QtGui>
+
+#include "qpropertytransform.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsItem *item = new QGraphicsRectItem(QRectF(0,0, 200, 100));
+ scene.addItem(item);
+ QPropertyTransform transform;
+ transform.setTargetItem(item);
+
+ QAnimationGroup *group = new QAnimationGroup(QAnimationGroup::Parallel, &scene);
+ QPropertyAnimation *scaleAnim = new QPropertyAnimation(&transform, "scaleX");
+ scaleAnim->setStartValue(1.0);
+ scaleAnim->setTargetValue(2.0);
+ scaleAnim->setDuration(10000);
+ group->add(scaleAnim);
+
+ QPropertyAnimation *scaleAnim2 = new QPropertyAnimation(&transform, "scaleY");
+ scaleAnim2->setStartValue(.0);
+ scaleAnim2->setTargetValue(2.0);
+ scaleAnim2->setDuration(10000);
+ QEasingCurve curve(QEasingCurve::InElastic);
+ curve.setPeriod(2);
+ curve.setAmplitude(2);
+
+ //scaleAnim2->setEasingCurve(curve);
+ //scaleAnim2->setEasingCurve(QEasingCurve(QEasingCurve::OutElastic , 2, 2 ));
+ group->add(scaleAnim2);
+
+ QPropertyAnimation *rotAnim = new QPropertyAnimation(&transform, "rotation");
+ rotAnim->setStartValue(0);
+ rotAnim->setTargetValue(90);
+ rotAnim->setDuration(10000);
+ group->add(rotAnim);
+
+ group->start();
+
+ view.resize(800,600);
+ view.show();
+ return app.exec();
+}
diff --git a/examples/animation/research/propertytransform/propertytransform.pro b/examples/animation/research/propertytransform/propertytransform.pro
new file mode 100644
index 0000000..94c36b8
--- /dev/null
+++ b/examples/animation/research/propertytransform/propertytransform.pro
@@ -0,0 +1,14 @@
+######################################################################
+# Automatically generated by qmake (2.01a) fr 26. sep 13:21:57 2008
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
+HEADERS += qpropertytransform.h
+CONFIG += console
+
diff --git a/examples/animation/research/propertytransform/qpropertytransform.h b/examples/animation/research/propertytransform/qpropertytransform.h
new file mode 100644
index 0000000..e052625
--- /dev/null
+++ b/examples/animation/research/propertytransform/qpropertytransform.h
@@ -0,0 +1,78 @@
+#include <QtCore/QObject>
+#include <QtCore/QPoint>
+#include <QtGui/QGraphicsItem>
+#include <QtGui/QTransform>
+#include <QtCore/QDebug>
+
+/**
+ * Experimental.
+ * Pros:
+ * 1. Does not add ugly/confusing API to QGraphicsItem.
+ *
+ * Cons:
+ * 1. apply() /m_item->setTransform() is called too many times. (FIXED NOW?)
+ *
+ *
+ */
+class QPropertyTransform : public QObject {
+ Q_OBJECT
+public:
+ Q_PROPERTY(QPointF center READ center WRITE setCenter);
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation);
+ Q_PROPERTY(qreal scaleX READ scaleX WRITE setScaleX);
+ Q_PROPERTY(qreal scaleY READ scaleY WRITE setScaleY);
+public:
+ QPropertyTransform() : m_item(0), m_rotationZ(0), m_scaleX(1.), m_scaleY(1.) {}
+
+ void setTargetItem(QGraphicsItem *item) {
+ m_item = item;
+ }
+
+ void setCenter(const QPointF &center) {
+ m_center = center;
+ apply();
+ }
+
+ QPointF center() const { return m_center; }
+
+ void setRotation(qreal rotation) {
+ m_rotationZ = rotation;
+ apply();
+ }
+
+ qreal rotation() const { return m_rotationZ; }
+
+ void setScaleX(qreal scale) {
+ m_scaleX = scale;
+ apply();
+ }
+
+ qreal scaleX() const { return m_scaleX; }
+
+ void setScaleY(qreal scale) {
+ m_scaleY = scale;
+ apply();
+ }
+
+ qreal scaleY() const { return m_scaleY; }
+
+private:
+ QTransform transform() const {
+ return QTransform().translate(m_center.x(), m_center.y())
+ .rotate(m_rotationZ)
+ .scale(m_scaleX, m_scaleY)
+ .translate(-m_center.x(), -m_center.y());
+ }
+
+ void apply() {
+ if (m_item)
+ m_item->setTransform(transform());
+ }
+
+ QGraphicsItem *m_item;
+ QPointF m_center;
+ qreal m_rotationZ;
+ qreal m_scaleX;
+ qreal m_scaleY;
+};
+
diff --git a/examples/animation/research/sound/main.cpp b/examples/animation/research/sound/main.cpp
new file mode 100644
index 0000000..2c9fa47
--- /dev/null
+++ b/examples/animation/research/sound/main.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//The purpose of this example is to show that it is possible to have your own
+// animation with undefined duration
+
+#include <QtGui/QtGui>
+#include <phonon>
+
+class SoundAnimation : public QAbstractAnimation
+{
+public:
+ SoundAnimation(const QString &file)
+ {
+ //in an idea case we should also control the errors
+ Phonon::createPath(&m_media, &m_audio);
+ m_media.setCurrentSource(file);
+ connect(&m_media, SIGNAL(finished()), SLOT(stop()));
+ }
+
+ int duration() const
+ {
+ return -1;
+ }
+
+ void updateCurrentTime(int msecs)
+ {
+ //nothing to do here...
+ qDebug() << "updateCurrentTime" << msecs;
+ }
+
+ void updateState(State state)
+ {
+ switch(state)
+ {
+ case Running:
+ m_media.play();
+ break;
+ case Stopped:
+ m_media.stop();
+ break;
+ case Paused:
+ m_media.pause();
+ break;
+ }
+ }
+
+
+private:
+ Phonon::MediaObject m_media;
+ Phonon::AudioOutput m_audio;
+
+};
+
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ Q_INIT_RESOURCE(sound);
+
+ SoundAnimation anim(QLatin1String(":/media/sax.mp3"));
+ app.connect(&anim, SIGNAL(finished()), SLOT(quit()));
+ anim.start();
+
+ return app.exec();
+} \ No newline at end of file
diff --git a/examples/animation/research/sound/media/sax.mp3 b/examples/animation/research/sound/media/sax.mp3
new file mode 100644
index 0000000..0a078b1
--- /dev/null
+++ b/examples/animation/research/sound/media/sax.mp3
Binary files differ
diff --git a/examples/animation/research/sound/sound.pro b/examples/animation/research/sound/sound.pro
new file mode 100644
index 0000000..0ad3050
--- /dev/null
+++ b/examples/animation/research/sound/sound.pro
@@ -0,0 +1,14 @@
+######################################################################
+# Automatically generated by qmake (2.01a) mer. 21. janv. 13:53:26 2009
+######################################################################
+
+TEMPLATE = app
+QT += phonon
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+RESOURCES = sound.qrc
+
+# Input
+SOURCES += main.cpp
diff --git a/examples/animation/research/sound/sound.qrc b/examples/animation/research/sound/sound.qrc
new file mode 100644
index 0000000..8919142
--- /dev/null
+++ b/examples/animation/research/sound/sound.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+<file>media/sax.mp3</file>
+</qresource>
+</RCC>
diff --git a/examples/animation/states/accessories-dictionary.png b/examples/animation/states/accessories-dictionary.png
new file mode 100644
index 0000000..e9bd55d
--- /dev/null
+++ b/examples/animation/states/accessories-dictionary.png
Binary files differ
diff --git a/examples/animation/states/akregator.png b/examples/animation/states/akregator.png
new file mode 100644
index 0000000..a086f45
--- /dev/null
+++ b/examples/animation/states/akregator.png
Binary files differ
diff --git a/examples/animation/states/digikam.png b/examples/animation/states/digikam.png
new file mode 100644
index 0000000..9de9fb2
--- /dev/null
+++ b/examples/animation/states/digikam.png
Binary files differ
diff --git a/examples/animation/states/help-browser.png b/examples/animation/states/help-browser.png
new file mode 100644
index 0000000..db92faa
--- /dev/null
+++ b/examples/animation/states/help-browser.png
Binary files differ
diff --git a/examples/animation/states/k3b.png b/examples/animation/states/k3b.png
new file mode 100644
index 0000000..bbcafcf
--- /dev/null
+++ b/examples/animation/states/k3b.png
Binary files differ
diff --git a/examples/animation/states/kchart.png b/examples/animation/states/kchart.png
new file mode 100644
index 0000000..1dd115b
--- /dev/null
+++ b/examples/animation/states/kchart.png
Binary files differ
diff --git a/examples/animation/states/main.cpp b/examples/animation/states/main.cpp
new file mode 100644
index 0000000..5c004a2
--- /dev/null
+++ b/examples/animation/states/main.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qstate.h"
+# include "qstatemachine.h"
+# include "qtransition.h"
+# include "qparallelanimationgroup.h"
+# include "qsequentialanimationgroup.h"
+# include "qpropertyanimation.h"
+#endif
+
+class Pixmap : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ Pixmap(const QPixmap &pix) : QGraphicsWidget(), p(pix)
+ {
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->drawPixmap(QPointF(), p);
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint, const QSizeF & = QSizeF())
+ {
+ return QSizeF(p.width(), p.height());
+ }
+
+private:
+ QPixmap p;
+};
+
+int main(int argc, char *argv[])
+{
+ Q_INIT_RESOURCE(states);
+
+ QApplication app(argc, argv);
+
+ // Text edit and button
+ QTextEdit *edit = new QTextEdit;
+ edit->setText("asdf lkjha yuoiqwe asd iuaysd u iasyd uiy "
+ "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy "
+ "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy "
+ "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy!");
+
+ QPushButton *button = new QPushButton;
+ QGraphicsProxyWidget *buttonProxy = new QGraphicsProxyWidget;
+ buttonProxy->setWidget(button);
+ QGraphicsProxyWidget *editProxy = new QGraphicsProxyWidget;
+ editProxy->setWidget(edit);
+
+ QGroupBox *box = new QGroupBox;
+ box->setFlat(true);
+ box->setTitle("Options");
+
+ QVBoxLayout *layout2 = new QVBoxLayout;
+ box->setLayout(layout2);
+ layout2->addWidget(new QRadioButton("Herring"));
+ layout2->addWidget(new QRadioButton("Blue Parrot"));
+ layout2->addWidget(new QRadioButton("Petunias"));
+ layout2->addStretch();
+
+ QGraphicsProxyWidget *boxProxy = new QGraphicsProxyWidget;
+ boxProxy->setWidget(box);
+
+ // Parent widget
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, widget);
+ layout->addItem(editProxy);
+ layout->addItem(buttonProxy);
+ widget->setLayout(layout);
+
+ Pixmap *p1 = new Pixmap(QPixmap(":/digikam.png"));
+ Pixmap *p2 = new Pixmap(QPixmap(":/akregator.png"));
+ Pixmap *p3 = new Pixmap(QPixmap(":/accessories-dictionary.png"));
+ Pixmap *p4 = new Pixmap(QPixmap(":/k3b.png"));
+ Pixmap *p5 = new Pixmap(QPixmap(":/help-browser.png"));
+ Pixmap *p6 = new Pixmap(QPixmap(":/kchart.png"));
+
+ QGraphicsScene scene(0, 0, 400, 300);
+ scene.setBackgroundBrush(scene.palette().window());
+ scene.addItem(widget);
+ scene.addItem(boxProxy);
+ scene.addItem(p1);
+ scene.addItem(p2);
+ scene.addItem(p3);
+ scene.addItem(p4);
+ scene.addItem(p5);
+ scene.addItem(p6);
+
+ QStateMachine machine;
+ QState *root = machine.rootState();
+ QState *state1 = new QState(root);
+ QState *state2 = new QState(root);
+ QState *state3 = new QState(root);
+ machine.setInitialState(state1);
+
+ // State 1
+ state1->setPropertyOnEntry(button, "text", "Switch to state 2");
+ state1->setPropertyOnEntry(widget, "geometry", QRectF(0, 0, 400, 150));
+ state1->setPropertyOnEntry(box, "geometry", QRect(-200, 150, 200, 150));
+ state1->setPropertyOnEntry(p1, "geometry", QRectF(68, 185, 64, 64));
+ state1->setPropertyOnEntry(p2, "geometry", QRectF(168, 185, 64, 64));
+ state1->setPropertyOnEntry(p3, "geometry", QRectF(268, 185, 64, 64));
+ state1->setPropertyOnEntry(p4, "geometry", QRectF(68-150, 48-150, 64, 64));
+ state1->setPropertyOnEntry(p5, "geometry", QRectF(168, 48-150, 64, 64));
+ state1->setPropertyOnEntry(p6, "geometry", QRectF(268+150, 48-150, 64, 64));
+ state1->setPropertyOnEntry(p1, "zRotation", qreal(0));
+ state1->setPropertyOnEntry(p2, "zRotation", qreal(0));
+ state1->setPropertyOnEntry(p3, "zRotation", qreal(0));
+ state1->setPropertyOnEntry(p4, "zRotation", qreal(-270));
+ state1->setPropertyOnEntry(p5, "zRotation", qreal(-90));
+ state1->setPropertyOnEntry(p6, "zRotation", qreal(270));
+ state1->setPropertyOnEntry(boxProxy, "opacity", qreal(0));
+ state1->setPropertyOnEntry(p1, "opacity", qreal(1));
+ state1->setPropertyOnEntry(p2, "opacity", qreal(1));
+ state1->setPropertyOnEntry(p3, "opacity", qreal(1));
+ state1->setPropertyOnEntry(p4, "opacity", qreal(0));
+ state1->setPropertyOnEntry(p5, "opacity", qreal(0));
+ state1->setPropertyOnEntry(p6, "opacity", qreal(0));
+
+ // State 2
+ state2->setPropertyOnEntry(button, "text", "Switch to state 3");
+ state2->setPropertyOnEntry(widget, "geometry", QRectF(200, 150, 200, 150));
+ state2->setPropertyOnEntry(box, "geometry", QRect(9, 150, 190, 150));
+ state2->setPropertyOnEntry(p1, "geometry", QRectF(68-150, 185+150, 64, 64));
+ state2->setPropertyOnEntry(p2, "geometry", QRectF(168, 185+150, 64, 64));
+ state2->setPropertyOnEntry(p3, "geometry", QRectF(268+150, 185+150, 64, 64));
+ state2->setPropertyOnEntry(p4, "geometry", QRectF(64, 48, 64, 64));
+ state2->setPropertyOnEntry(p5, "geometry", QRectF(168, 48, 64, 64));
+ state2->setPropertyOnEntry(p6, "geometry", QRectF(268, 48, 64, 64));
+ state2->setPropertyOnEntry(p1, "zRotation", qreal(-270));
+ state2->setPropertyOnEntry(p2, "zRotation", qreal(90));
+ state2->setPropertyOnEntry(p3, "zRotation", qreal(270));
+ state2->setPropertyOnEntry(p4, "zRotation", qreal(0));
+ state2->setPropertyOnEntry(p5, "zRotation", qreal(0));
+ state2->setPropertyOnEntry(p6, "zRotation", qreal(0));
+ state2->setPropertyOnEntry(boxProxy, "opacity", qreal(1));
+ state2->setPropertyOnEntry(p1, "opacity", qreal(0));
+ state2->setPropertyOnEntry(p2, "opacity", qreal(0));
+ state2->setPropertyOnEntry(p3, "opacity", qreal(0));
+ state2->setPropertyOnEntry(p4, "opacity", qreal(1));
+ state2->setPropertyOnEntry(p5, "opacity", qreal(1));
+ state2->setPropertyOnEntry(p6, "opacity", qreal(1));
+
+ // State 3
+ state3->setPropertyOnEntry(button, "text", "Switch to state 1");
+ state3->setPropertyOnEntry(p1, "geometry", QRectF(5, 5, 64, 64));
+ state3->setPropertyOnEntry(p2, "geometry", QRectF(5, 5 + 64 + 5, 64, 64));
+ state3->setPropertyOnEntry(p3, "geometry", QRectF(5, 5 + (64 + 5) + 64, 64, 64));
+ state3->setPropertyOnEntry(p4, "geometry", QRectF(5 + 64 + 5, 5, 64, 64));
+ state3->setPropertyOnEntry(p5, "geometry", QRectF(5 + 64 + 5, 5 + 64 + 5, 64, 64));
+ state3->setPropertyOnEntry(p6, "geometry", QRectF(5 + 64 + 5, 5 + (64 + 5) + 64, 64, 64));
+ state3->setPropertyOnEntry(widget, "geometry", QRectF(138, 5, 400 - 138, 200));
+ state3->setPropertyOnEntry(box, "geometry", QRect(5, 205, 400, 90));
+ state3->setPropertyOnEntry(p1, "opacity", qreal(1));
+ state3->setPropertyOnEntry(p2, "opacity", qreal(1));
+ state3->setPropertyOnEntry(p3, "opacity", qreal(1));
+ state3->setPropertyOnEntry(p4, "opacity", qreal(1));
+ state3->setPropertyOnEntry(p5, "opacity", qreal(1));
+ state3->setPropertyOnEntry(p6, "opacity", qreal(1));
+
+ QParallelAnimationGroup animation1;
+
+ QSequentialAnimationGroup *animation1SubGroup;
+ animation1SubGroup = new QSequentialAnimationGroup(&animation1);
+ animation1SubGroup->addPause(250);
+ animation1SubGroup->addAnimation(new QPropertyAnimation(box, "geometry"));
+
+ animation1.addAnimation(new QPropertyAnimation(widget, "geometry"));
+ animation1.addAnimation(new QPropertyAnimation(p1, "geometry"));
+ animation1.addAnimation(new QPropertyAnimation(p2, "geometry"));
+ animation1.addAnimation(new QPropertyAnimation(p3, "geometry"));
+ animation1.addAnimation(new QPropertyAnimation(p4, "geometry"));
+ animation1.addAnimation(new QPropertyAnimation(p5, "geometry"));
+ animation1.addAnimation(new QPropertyAnimation(p6, "geometry"));
+ animation1.addAnimation(new QPropertyAnimation(p1, "zRotation"));
+ animation1.addAnimation(new QPropertyAnimation(p2, "zRotation"));
+ animation1.addAnimation(new QPropertyAnimation(p3, "zRotation"));
+ animation1.addAnimation(new QPropertyAnimation(p4, "zRotation"));
+ animation1.addAnimation(new QPropertyAnimation(p5, "zRotation"));
+ animation1.addAnimation(new QPropertyAnimation(p6, "zRotation"));
+ animation1.addAnimation(new QPropertyAnimation(p1, "opacity"));
+ animation1.addAnimation(new QPropertyAnimation(p2, "opacity"));
+ animation1.addAnimation(new QPropertyAnimation(p3, "opacity"));
+ animation1.addAnimation(new QPropertyAnimation(p4, "opacity"));
+ animation1.addAnimation(new QPropertyAnimation(p5, "opacity"));
+ animation1.addAnimation(new QPropertyAnimation(p6, "opacity"));
+
+ QParallelAnimationGroup animation2;
+ animation2.addAnimation(new QPropertyAnimation(box, "geometry"));
+ animation2.addAnimation(new QPropertyAnimation(widget, "geometry"));
+ animation2.addAnimation(new QPropertyAnimation(p1, "geometry"));
+ animation2.addAnimation(new QPropertyAnimation(p2, "geometry"));
+ animation2.addAnimation(new QPropertyAnimation(p3, "geometry"));
+ animation2.addAnimation(new QPropertyAnimation(p4, "geometry"));
+ animation2.addAnimation(new QPropertyAnimation(p5, "geometry"));
+ animation2.addAnimation(new QPropertyAnimation(p6, "geometry"));
+ animation2.addAnimation(new QPropertyAnimation(p1, "zRotation"));
+ animation2.addAnimation(new QPropertyAnimation(p2, "zRotation"));
+ animation2.addAnimation(new QPropertyAnimation(p3, "zRotation"));
+ animation2.addAnimation(new QPropertyAnimation(p4, "zRotation"));
+ animation2.addAnimation(new QPropertyAnimation(p5, "zRotation"));
+ animation2.addAnimation(new QPropertyAnimation(p6, "zRotation"));
+ animation2.addAnimation(new QPropertyAnimation(p1, "opacity"));
+ animation2.addAnimation(new QPropertyAnimation(p2, "opacity"));
+ animation2.addAnimation(new QPropertyAnimation(p3, "opacity"));
+ animation2.addAnimation(new QPropertyAnimation(p4, "opacity"));
+ animation2.addAnimation(new QPropertyAnimation(p5, "opacity"));
+ animation2.addAnimation(new QPropertyAnimation(p6, "opacity"));
+
+ QParallelAnimationGroup animation3;
+ animation3.addAnimation(new QPropertyAnimation(box, "geometry"));
+ animation3.addAnimation(new QPropertyAnimation(widget, "geometry"));
+ animation3.addAnimation(new QPropertyAnimation(p1, "geometry"));
+ animation3.addAnimation(new QPropertyAnimation(p2, "geometry"));
+ animation3.addAnimation(new QPropertyAnimation(p3, "geometry"));
+ animation3.addAnimation(new QPropertyAnimation(p4, "geometry"));
+ animation3.addAnimation(new QPropertyAnimation(p5, "geometry"));
+ animation3.addAnimation(new QPropertyAnimation(p6, "geometry"));
+ animation3.addAnimation(new QPropertyAnimation(p1, "zRotation"));
+ animation3.addAnimation(new QPropertyAnimation(p2, "zRotation"));
+ animation3.addAnimation(new QPropertyAnimation(p3, "zRotation"));
+ animation3.addAnimation(new QPropertyAnimation(p4, "zRotation"));
+ animation3.addAnimation(new QPropertyAnimation(p5, "zRotation"));
+ animation3.addAnimation(new QPropertyAnimation(p6, "zRotation"));
+ animation3.addAnimation(new QPropertyAnimation(p1, "opacity"));
+ animation3.addAnimation(new QPropertyAnimation(p2, "opacity"));
+ animation3.addAnimation(new QPropertyAnimation(p3, "opacity"));
+ animation3.addAnimation(new QPropertyAnimation(p4, "opacity"));
+ animation3.addAnimation(new QPropertyAnimation(p5, "opacity"));
+ animation3.addAnimation(new QPropertyAnimation(p6, "opacity"));
+
+ state1->addAnimatedTransition(button, SIGNAL(clicked()), state2, &animation1);
+ state2->addAnimatedTransition(button, SIGNAL(clicked()), state3, &animation2);
+ state3->addAnimatedTransition(button, SIGNAL(clicked()), state1, &animation3);
+
+ machine.start();
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/examples/animation/states/states.pro b/examples/animation/states/states.pro
new file mode 100644
index 0000000..f4d1e0b
--- /dev/null
+++ b/examples/animation/states/states.pro
@@ -0,0 +1,8 @@
+SOURCES += main.cpp
+RESOURCES += states.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/animation/states
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS states.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/animation/states
+INSTALLS += target sources
diff --git a/examples/animation/states/states.qrc b/examples/animation/states/states.qrc
new file mode 100644
index 0000000..60ab3f7
--- /dev/null
+++ b/examples/animation/states/states.qrc
@@ -0,0 +1,10 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>accessories-dictionary.png</file>
+ <file>akregator.png</file>
+ <file>digikam.png</file>
+ <file>help-browser.png</file>
+ <file>k3b.png</file>
+ <file>kchart.png</file>
+</qresource>
+</RCC>
diff --git a/examples/animation/stickman/animation.cpp b/examples/animation/stickman/animation.cpp
new file mode 100644
index 0000000..998632a
--- /dev/null
+++ b/examples/animation/stickman/animation.cpp
@@ -0,0 +1,152 @@
+#include "animation.h"
+
+#include <QPointF>
+#include <QIODevice>
+#include <QDataStream>
+
+class Frame
+{
+public:
+ Frame() {
+ }
+
+ int nodeCount() const
+ {
+ return m_nodePositions.size();
+ }
+
+ void setNodeCount(int nodeCount)
+ {
+ while (nodeCount > m_nodePositions.size())
+ m_nodePositions.append(QPointF());
+
+ while (nodeCount < m_nodePositions.size())
+ m_nodePositions.removeLast();
+ }
+
+ QPointF nodePos(int idx) const
+ {
+ return m_nodePositions.at(idx);
+ }
+
+ void setNodePos(int idx, const QPointF &pos)
+ {
+ m_nodePositions[idx] = pos;
+ }
+
+private:
+ QList<QPointF> m_nodePositions;
+};
+
+Animation::Animation()
+{
+ m_currentFrame = 0;
+ m_frames.append(new Frame);
+}
+
+Animation::~Animation()
+{
+ qDeleteAll(m_frames);
+}
+
+void Animation::setTotalFrames(int totalFrames)
+{
+ while (m_frames.size() < totalFrames)
+ m_frames.append(new Frame);
+
+ while (totalFrames < m_frames.size())
+ delete m_frames.takeLast();
+}
+
+int Animation::totalFrames() const
+{
+ return m_frames.size();
+}
+
+void Animation::setCurrentFrame(int currentFrame)
+{
+ m_currentFrame = qMax(qMin(currentFrame, totalFrames()-1), 0);
+}
+
+int Animation::currentFrame() const
+{
+ return m_currentFrame;
+}
+
+void Animation::setNodeCount(int nodeCount)
+{
+ Frame *frame = m_frames.at(m_currentFrame);
+ frame->setNodeCount(nodeCount);
+}
+
+int Animation::nodeCount() const
+{
+ Frame *frame = m_frames.at(m_currentFrame);
+ return frame->nodeCount();
+}
+
+void Animation::setNodePos(int idx, const QPointF &pos)
+{
+ Frame *frame = m_frames.at(m_currentFrame);
+ frame->setNodePos(idx, pos);
+}
+
+QPointF Animation::nodePos(int idx) const
+{
+ Frame *frame = m_frames.at(m_currentFrame);
+ return frame->nodePos(idx);
+}
+
+QString Animation::name() const
+{
+ return m_name;
+}
+
+void Animation::setName(const QString &name)
+{
+ m_name = name;
+}
+
+void Animation::save(QIODevice *device) const
+{
+ QDataStream stream(device);
+ stream << m_name;
+ stream << m_frames.size();
+ foreach (Frame *frame, m_frames) {
+ stream << frame->nodeCount();
+ for (int i=0; i<frame->nodeCount(); ++i)
+ stream << frame->nodePos(i);
+ }
+}
+
+void Animation::load(QIODevice *device)
+{
+ if (!m_frames.isEmpty())
+ qDeleteAll(m_frames);
+
+ m_frames.clear();
+
+ QDataStream stream(device);
+ stream >> m_name;
+
+ int frameCount;
+ stream >> frameCount;
+
+ for (int i=0; i<frameCount; ++i) {
+
+ int nodeCount;
+ stream >> nodeCount;
+
+ Frame *frame = new Frame;
+ frame->setNodeCount(nodeCount);
+
+ for (int j=0; j<nodeCount; ++j) {
+ QPointF pos;
+ stream >> pos;
+
+ frame->setNodePos(j, pos);
+ }
+
+ m_frames.append(frame);
+ }
+} \ No newline at end of file
diff --git a/examples/animation/stickman/animation.h b/examples/animation/stickman/animation.h
new file mode 100644
index 0000000..22afab6
--- /dev/null
+++ b/examples/animation/stickman/animation.h
@@ -0,0 +1,40 @@
+#ifndef ANIMATION_H
+#define ANIMATION_H
+
+#include <QPointF>
+#include <QList>
+#include <QString>
+
+class Frame;
+class QIODevice;
+class Animation
+{
+public:
+ Animation();
+ ~Animation();
+
+ void setTotalFrames(int totalFrames);
+ int totalFrames() const;
+
+ void setCurrentFrame(int currentFrame);
+ int currentFrame() const;
+
+ void setNodeCount(int nodeCount);
+ int nodeCount() const;
+
+ void setNodePos(int idx, const QPointF &pos);
+ QPointF nodePos(int idx) const;
+
+ QString name() const;
+ void setName(const QString &name);
+
+ void save(QIODevice *device) const;
+ void load(QIODevice *device);
+
+private:
+ QString m_name;
+ QList<Frame *> m_frames;
+ int m_currentFrame;
+};
+
+#endif
diff --git a/examples/animation/stickman/animations/chilling b/examples/animation/stickman/animations/chilling
new file mode 100644
index 0000000..a81fc7a
--- /dev/null
+++ b/examples/animation/stickman/animations/chilling
Binary files differ
diff --git a/examples/animation/stickman/animations/dancing b/examples/animation/stickman/animations/dancing
new file mode 100644
index 0000000..462f66f
--- /dev/null
+++ b/examples/animation/stickman/animations/dancing
Binary files differ
diff --git a/examples/animation/stickman/animations/dead b/examples/animation/stickman/animations/dead
new file mode 100644
index 0000000..9859b4b
--- /dev/null
+++ b/examples/animation/stickman/animations/dead
Binary files differ
diff --git a/examples/animation/stickman/animations/jumping b/examples/animation/stickman/animations/jumping
new file mode 100644
index 0000000..12661a1
--- /dev/null
+++ b/examples/animation/stickman/animations/jumping
Binary files differ
diff --git a/examples/animation/stickman/graphicsview.cpp b/examples/animation/stickman/graphicsview.cpp
new file mode 100644
index 0000000..1b6afa9
--- /dev/null
+++ b/examples/animation/stickman/graphicsview.cpp
@@ -0,0 +1,15 @@
+#include "graphicsview.h"
+
+#include <QtGui/QKeyEvent>
+
+GraphicsView::GraphicsView(QWidget *parent) : QGraphicsView(parent) {}
+
+void GraphicsView::keyPressEvent(QKeyEvent *e)
+{
+ if (e->key() == Qt::Key_Escape)
+ close();
+
+ emit keyPressed(Qt::Key(e->key()));
+}
+
+
diff --git a/examples/animation/stickman/graphicsview.h b/examples/animation/stickman/graphicsview.h
new file mode 100644
index 0000000..9ea2cfb
--- /dev/null
+++ b/examples/animation/stickman/graphicsview.h
@@ -0,0 +1,19 @@
+#ifndef GRAPHICSVIEW_H
+#define GRAPHICSVIEW
+
+#include <QtGui/QGraphicsView>
+
+class GraphicsView: public QGraphicsView
+{
+ Q_OBJECT
+public:
+ GraphicsView(QWidget *parent = 0);
+
+protected:
+ void keyPressEvent(QKeyEvent *);
+
+signals:
+ void keyPressed(int key);
+};
+
+#endif
diff --git a/examples/animation/stickman/lifecycle.cpp b/examples/animation/stickman/lifecycle.cpp
new file mode 100644
index 0000000..3e92aec
--- /dev/null
+++ b/examples/animation/stickman/lifecycle.cpp
@@ -0,0 +1,176 @@
+#include "lifecycle.h"
+#include "stickman.h"
+#include "node.h"
+#include "animation.h"
+#include "graphicsview.h"
+
+#include <QtCore>
+#include <QtGui>
+
+class KeyPressTransition: public QSignalTransition
+{
+public:
+ KeyPressTransition(GraphicsView *receiver, Qt::Key key)
+ : QSignalTransition(receiver, SIGNAL(keyPressed(int))), m_key(key)
+ {
+ }
+ KeyPressTransition(GraphicsView *receiver, Qt::Key key, QAbstractState *target)
+ : QSignalTransition(receiver, SIGNAL(keyPressed(int)), QList<QAbstractState*>() << target), m_key(key)
+ {
+ }
+
+ virtual bool eventTest(QEvent *e) const
+ {
+ if (QSignalTransition::eventTest(e)) {
+ QVariant key = static_cast<QSignalEvent*>(e)->arguments().at(0);
+ return (key.toInt() == int(m_key));
+ }
+
+ return false;
+ }
+private:
+ Qt::Key m_key;
+};
+
+class LightningStrikesTransition: public QEventTransition
+{
+public:
+ LightningStrikesTransition(QAbstractState *target)
+ : QEventTransition(this, QEvent::Timer, QList<QAbstractState*>() << target)
+ {
+ qsrand((uint)QDateTime::currentDateTime().toTime_t());
+ startTimer(1000);
+ }
+
+ virtual bool eventTest(QEvent *e) const
+ {
+ return QEventTransition::eventTest(e) && ((qrand() % 50) == 0);
+ }
+};
+
+LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver)
+ : m_stickMan(stickMan), m_keyReceiver(keyReceiver)
+{
+ // Create animation group to be used for all transitions
+ m_animationGroup = new QParallelAnimationGroup();
+ const int stickManNodeCount = m_stickMan->nodeCount();
+ for (int i=0; i<stickManNodeCount; ++i) {
+ QPropertyAnimation *pa = new QPropertyAnimation(m_stickMan->node(i), "position");
+ m_animationGroup->addAnimation(pa);
+ }
+
+ // Set up intial state graph
+ m_machine = new QStateMachine();
+ m_machine->setGlobalRestorePolicy(QState::RestoreProperties);
+
+ m_alive = new QState(m_machine->rootState());
+ m_alive->setObjectName("alive");
+
+ // Make it blink when lightning strikes before entering dead animation
+ QState *lightningBlink = new QState(m_machine->rootState());
+ lightningBlink->setRestorePolicy(QState::DoNotRestoreProperties);
+ lightningBlink->setPropertyOnEntry(m_stickMan->scene(), "backgroundBrush", Qt::white);
+ lightningBlink->setPropertyOnEntry(m_stickMan, "penColor", Qt::black);
+ lightningBlink->setPropertyOnEntry(m_stickMan, "fillColor", Qt::white);
+ lightningBlink->setPropertyOnEntry(m_stickMan, "isDead", true);
+
+ m_dead = new QState(m_machine->rootState());
+ m_dead->setRestorePolicy(QState::DoNotRestoreProperties);
+ m_dead->setPropertyOnEntry(m_stickMan->scene(), "backgroundBrush", Qt::black);
+ m_dead->setPropertyOnEntry(m_stickMan, "penColor", Qt::white);
+ m_dead->setPropertyOnEntry(m_stickMan, "fillColor", Qt::black);
+ m_dead->setObjectName("dead");
+
+ // Idle state (sets no properties)
+ m_idle = new QState(m_alive);
+ m_idle->setObjectName("idle");
+ m_alive->setInitialState(m_idle);
+
+ // Lightning strikes at random
+ m_alive->addTransition(new LightningStrikesTransition(lightningBlink));
+ m_alive->addTransition(new KeyPressTransition(m_keyReceiver, Qt::Key_L, lightningBlink));
+ connectByAnimation(m_machine->rootState(), lightningBlink, m_dead);
+
+ m_machine->setInitialState(m_alive);
+}
+
+void LifeCycle::setResetKey(Qt::Key resetKey)
+{
+ // When resetKey is pressed, enter the idle state and do a restoration animation
+ // (requires no animation pointer, since no property is being set in the idle state)
+ m_alive->addAnimatedTransition(new KeyPressTransition(m_keyReceiver, resetKey, m_idle));
+}
+
+void LifeCycle::setDeathAnimation(const QString &fileName)
+{
+ QState *deathAnimation = makeState(m_dead, fileName);
+ m_dead->setInitialState(deathAnimation);
+}
+
+void LifeCycle::start()
+{
+ m_machine->start();
+}
+
+void LifeCycle::connectByAnimation(QState *parentState,
+ QState *s1, QAbstractState *s2,
+ QAbstractTransition *transition)
+{
+ QAnimationState *animationState = new QAnimationState(m_animationGroup, parentState);
+
+ if (transition == 0)
+ s1->addTransition(animationState);
+ else {
+ transition->setTargetStates(QList<QAbstractState*>() << animationState);
+ s1->addTransition(transition);
+ }
+
+ animationState->addFinishedTransition(s2);
+}
+
+void LifeCycle::addActivity(const QString &fileName, Qt::Key key)
+{
+ QState *state = makeState(m_alive, fileName);
+ connectByAnimation(m_alive, m_alive, state, new KeyPressTransition(m_keyReceiver, key));
+}
+
+QState *LifeCycle::makeState(QState *parentState, const QString &animationFileName)
+{
+ QState *topLevel = new QState(parentState);
+
+ Animation animation;
+ {
+ QFile file(animationFileName);
+ if (file.open(QIODevice::ReadOnly))
+ animation.load(&file);
+ }
+
+ const int frameCount = animation.totalFrames();
+ QState *previousState = 0;
+ for (int i=0; i<frameCount; ++i) {
+ QState *frameState = new QState(topLevel);
+
+ animation.setCurrentFrame(i);
+ const int nodeCount = animation.nodeCount();
+ for (int j=0; j<nodeCount; ++j)
+ frameState->setPropertyOnEntry(m_stickMan->node(j), "position", animation.nodePos(j));
+
+ if (previousState == 0)
+ topLevel->setInitialState(frameState);
+ else
+ connectByAnimation(topLevel, previousState, frameState);
+ previousState = frameState;
+ }
+
+ // Loop
+ connectByAnimation(topLevel, previousState, topLevel->initialState());
+
+ return topLevel;
+
+}
+
+LifeCycle::~LifeCycle()
+{
+ delete m_machine;
+ delete m_animationGroup;
+}
diff --git a/examples/animation/stickman/lifecycle.h b/examples/animation/stickman/lifecycle.h
new file mode 100644
index 0000000..8094a76
--- /dev/null
+++ b/examples/animation/stickman/lifecycle.h
@@ -0,0 +1,40 @@
+#ifndef LIFECYCLE_H
+#define LIFECYCLE_H
+
+#include <Qt>
+
+class StickMan;
+class QStateMachine;
+class QAnimationGroup;
+class QState;
+class QAbstractState;
+class QAbstractTransition;
+class GraphicsView;
+class LifeCycle
+{
+public:
+ LifeCycle(StickMan *stickMan, GraphicsView *keyEventReceiver);
+ ~LifeCycle();
+
+ void setDeathAnimation(const QString &fileName);
+ void setResetKey(Qt::Key key);
+ void addActivity(const QString &fileName, Qt::Key key);
+
+ void start();
+
+private:
+ void connectByAnimation(QState *parentState, QState *s1, QAbstractState *s2,
+ QAbstractTransition *transition = 0);
+ QState *makeState(QState *parentState, const QString &animationFileName);
+
+ StickMan *m_stickMan;
+ QStateMachine *m_machine;
+ QAnimationGroup *m_animationGroup;
+ GraphicsView *m_keyReceiver;
+
+ QState *m_alive;
+ QState *m_dead;
+ QState *m_idle;
+};
+
+#endif
diff --git a/examples/animation/stickman/main.cpp b/examples/animation/stickman/main.cpp
new file mode 100644
index 0000000..a094e28
--- /dev/null
+++ b/examples/animation/stickman/main.cpp
@@ -0,0 +1,58 @@
+#include "animation.h"
+#include "node.h"
+#include "lifecycle.h"
+#include "stickman.h"
+#include "graphicsview.h"
+
+#include <QtCore>
+#include <QtGui>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ StickMan *stickMan = new StickMan;
+ stickMan->setDrawSticks(false);
+
+ QGraphicsTextItem *textItem = new QGraphicsTextItem();
+ textItem->setHtml("<font color=\"white\"><b>Stickman</b>"
+ "<p>"
+ "Tell the stickman what to do!"
+ "</p>"
+ "<p><i>"
+ "<li>Press <font color=\"purple\">J</font> to make the stickman jump.</li>"
+ "<li>Press <font color=\"purple\">D</font> to make the stickman dance.</li>"
+ "<li>Press <font color=\"purple\">C</font> to make him chill out.</li>"
+ "<li>Press <font color=\"purple\">Return</font> to make him return to his original position.</li>"
+ "<li>When you are done, press <font color=\"purple\">Escape</font>.</li>"
+ "</i></p>"
+ "<p>If you are unlucky, the stickman will get struck by lightning, and never jump, dance or chill out again."
+ "</p></font>");
+ qreal w = textItem->boundingRect().width();
+ QRectF stickManBoundingRect = stickMan->mapToScene(stickMan->boundingRect()).boundingRect();
+ textItem->setPos(-w / 2.0, stickManBoundingRect.bottom() + 25.0);
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ scene->addItem(stickMan);
+ scene->addItem(textItem);
+ scene->setBackgroundBrush(Qt::black);
+
+ GraphicsView *view = new GraphicsView();
+ view->setRenderHints(QPainter::Antialiasing);
+ view->setTransformationAnchor(QGraphicsView::NoAnchor);
+ view->setScene(scene);
+ view->showFullScreen();
+ view->setFocus();
+ view->setSceneRect(scene->sceneRect());
+
+ LifeCycle *cycle = new LifeCycle(stickMan, view);
+ cycle->setResetKey(Qt::Key_Return);
+ cycle->setDeathAnimation("animations/dead");
+
+ cycle->addActivity("animations/jumping", Qt::Key_J);
+ cycle->addActivity("animations/dancing", Qt::Key_D);
+ cycle->addActivity("animations/chilling", Qt::Key_C);
+ cycle->start();
+
+ return app.exec();
+}
diff --git a/examples/animation/stickman/node.cpp b/examples/animation/stickman/node.cpp
new file mode 100644
index 0000000..f3468d0
--- /dev/null
+++ b/examples/animation/stickman/node.cpp
@@ -0,0 +1,42 @@
+#include "node.h"
+
+#include <QRectF>
+#include <QPainter>
+#include <QGraphicsSceneMouseEvent>
+
+Node::Node(const QPointF &pos, QGraphicsItem *parent)
+ : QGraphicsItem(parent), m_dragging(false)
+{
+ setPos(pos);
+}
+
+Node::~Node()
+{
+}
+
+QRectF Node::boundingRect() const
+{
+ return QRectF(-6.0, -6.0, 12.0, 12.0);
+}
+
+void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ painter->setPen(Qt::white);
+ painter->drawEllipse(QPointF(0.0, 0.0), 5.0, 5.0);
+}
+
+void Node::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ m_dragging = true;
+}
+
+void Node::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+ if (m_dragging)
+ setPos(mapToParent(event->pos()));
+}
+
+void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ m_dragging = false;
+} \ No newline at end of file
diff --git a/examples/animation/stickman/node.h b/examples/animation/stickman/node.h
new file mode 100644
index 0000000..b796774
--- /dev/null
+++ b/examples/animation/stickman/node.h
@@ -0,0 +1,26 @@
+#ifndef NODE_H
+#define NODE_H
+
+#include <QGraphicsItem>
+
+class Node: public QObject, public QGraphicsItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QPointF position READ pos WRITE setPos);
+public:
+ Node(const QPointF &pos, QGraphicsItem *parent = 0);
+ ~Node();
+
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *);
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
+
+private:
+ bool m_dragging;
+};
+
+#endif
diff --git a/examples/animation/stickman/stickman.cpp b/examples/animation/stickman/stickman.cpp
new file mode 100644
index 0000000..22d48d3
--- /dev/null
+++ b/examples/animation/stickman/stickman.cpp
@@ -0,0 +1,299 @@
+#include "stickman.h"
+#include "node.h"
+
+#include <QPainter>
+#include <QTimer>
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+static const int NodeCount = 16;
+static const qreal Coords[NodeCount * 2] = {
+ 0.0, -150.0, // head, #0
+
+ 0.0, -100.0, // body pentagon, top->bottom, left->right, #1 - 5
+ -50.0, -50.0,
+ 50.0, -50.0,
+ -25.0, 50.0,
+ 25.0, 50.0,
+
+ -100.0, 0.0, // right arm, #6 - 7
+ -125.0, 50.0,
+
+ 100.0, 0.0, // left arm, #8 - 9
+ 125.0, 50.0,
+
+ -35.0, 75.0, // lower body, #10 - 11
+ 35.0, 75.0,
+
+ -25.0, 200.0, // right leg, #12 - 13
+ -30.0, 300.0,
+
+ 25.0, 200.0, // left leg, #14 - 15
+ 30.0, 300.0
+
+};
+
+static const int BoneCount = 24;
+static const int Bones[BoneCount * 2] = {
+ 0, 1, // neck
+
+ 1, 2, // body
+ 1, 3,
+ 1, 4,
+ 1, 5,
+ 2, 3,
+ 2, 4,
+ 2, 5,
+ 3, 4,
+ 3, 5,
+ 4, 5,
+
+ 2, 6, // right arm
+ 6, 7,
+
+ 3, 8, // left arm
+ 8, 9,
+
+ 4, 10, // lower body
+ 4, 11,
+ 5, 10,
+ 5, 11,
+ 10, 11,
+
+ 10, 12, // right leg
+ 12, 13,
+
+ 11, 14, // left leg
+ 14, 15
+
+};
+
+StickMan::StickMan()
+{
+ m_nodes = new Node*[NodeCount];
+ m_sticks = true;
+ m_isDead = false;
+ m_pixmap = QPixmap("images/head.png");
+ m_penColor = Qt::white;
+ m_fillColor = Qt::black;
+
+ // Set up start position of limbs
+ for (int i=0; i<NodeCount; ++i) {
+ m_nodes[i] = new Node(QPointF(Coords[i * 2], Coords[i * 2 + 1]), this);
+ }
+
+ m_perfectBoneLengths = new qreal[BoneCount];
+ for (int i=0; i<BoneCount; ++i) {
+ int n1 = Bones[i * 2];
+ int n2 = Bones[i * 2 + 1];
+
+ Node *node1 = m_nodes[n1];
+ Node *node2 = m_nodes[n2];
+
+ QPointF dist = node1->pos() - node2->pos();
+ m_perfectBoneLengths[i] = sqrt(pow(dist.x(),2) + pow(dist.y(),2));
+ }
+
+ startTimer(10);
+}
+
+StickMan::~StickMan()
+{
+ delete m_nodes;
+}
+
+void StickMan::setDrawSticks(bool on)
+{
+ m_sticks = on;
+ for (int i=0;i<nodeCount();++i) {
+ Node *node = m_nodes[i];
+ node->setVisible(on);
+ }
+}
+
+QRectF StickMan::boundingRect() const
+{
+ // account for head radius=50.0 plus pen which is 5.0, plus jump height :-)
+ return QRectF(-125, -200, 250, 450 + 50).adjusted(-55.0, -55.0, 55.0, 55.0);
+}
+
+int StickMan::nodeCount() const
+{
+ return NodeCount;
+}
+
+Node *StickMan::node(int idx) const
+{
+ const_cast<StickMan *>(this)->prepareGeometryChange();
+ if (idx >= 0 && idx < NodeCount)
+ return m_nodes[idx];
+ else
+ return 0;
+}
+
+void StickMan::timerEvent(QTimerEvent *e)
+{
+ prepareGeometryChange();
+}
+
+void StickMan::stabilize()
+{
+ for (int i=0; i<BoneCount; ++i) {
+ int n1 = Bones[i * 2];
+ int n2 = Bones[i * 2 + 1];
+
+ Node *node1 = m_nodes[n1];
+ Node *node2 = m_nodes[n2];
+
+ QPointF pos1 = node1->pos();
+ QPointF pos2 = node2->pos();
+
+ QPointF dist = pos1 - pos2;
+ qreal length = sqrt(pow(dist.x(),2) + pow(dist.y(),2));
+ qreal diff = (length - m_perfectBoneLengths[i]) / length;
+
+ pos1 -= dist * (0.5 * diff);
+ pos2 += dist * (0.5 * diff);
+
+ node1->setPos(pos1);
+ node2->setPos(pos2);
+
+ }
+}
+
+QPointF StickMan::posFor(int idx) const
+{
+ return m_nodes[idx]->pos();
+}
+
+//#include <QTime>
+void StickMan::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ /* static int frames = 0;
+ static QTime time;
+ if (frames++ % 100 == 0) {
+ frames = 1;
+ time.restart();
+ }
+
+ if (time.elapsed() > 0) {
+ painter->setPen(Qt::white);
+ painter->drawText(0, 0, QString::number(frames / (time.elapsed() / 1000.0)));
+ }*/
+
+ stabilize();
+ if (m_sticks) {
+ painter->setPen(Qt::white);
+ for (int i=0; i<BoneCount; ++i) {
+ int n1 = Bones[i * 2];
+ int n2 = Bones[i * 2 + 1];
+
+ Node *node1 = m_nodes[n1];
+ Node *node2 = m_nodes[n2];
+
+ painter->drawLine(node1->pos(), node2->pos());
+ }
+ } else {
+ // first bone is neck and will be used for head
+
+ QPainterPath path;
+ path.moveTo(posFor(0));
+ path.lineTo(posFor(1));
+
+ // right arm
+ path.lineTo(posFor(2));
+ path.lineTo(posFor(6));
+ path.lineTo(posFor(7));
+
+ // left arm
+ path.moveTo(posFor(3));
+ path.lineTo(posFor(8));
+ path.lineTo(posFor(9));
+
+ // body
+ path.moveTo(posFor(2));
+ path.lineTo(posFor(4));
+ path.lineTo(posFor(10));
+ path.lineTo(posFor(11));
+ path.lineTo(posFor(5));
+ path.lineTo(posFor(3));
+ path.lineTo(posFor(1));
+
+ // right leg
+ path.moveTo(posFor(10));
+ path.lineTo(posFor(12));
+ path.lineTo(posFor(13));
+
+ // left leg
+ path.moveTo(posFor(11));
+ path.lineTo(posFor(14));
+ path.lineTo(posFor(15));
+
+ painter->setPen(QPen(m_penColor, 5.0, Qt::SolidLine, Qt::RoundCap));
+ painter->drawPath(path);
+
+ {
+ int n1 = Bones[0];
+ int n2 = Bones[1];
+ Node *node1 = m_nodes[n1];
+ Node *node2 = m_nodes[n2];
+
+ QPointF dist = node2->pos() - node1->pos();
+
+ qreal sinAngle = dist.x() / sqrt(pow(dist.x(), 2) + pow(dist.y(), 2));
+ qreal angle = asin(sinAngle) * 180.0 / M_PI;
+
+ QPointF headPos = node1->pos();
+ painter->save();
+ painter->translate(headPos);
+ painter->rotate(-angle);
+
+ painter->setBrush(m_fillColor);
+ painter->drawEllipse(QPointF(0,0), 50.0, 50.0);
+
+ /*painter->drawArc(QRectF(-20.0, 0.0, 40.0, 20.0), 30.0 * 16, 120.0 * 16);
+
+ painter->setBrush(m_penColor);
+ painter->drawEllipse(QPointF(-30.0, -30.0), 2.5, 2.5);
+ painter->drawEllipse(QPointF(30.0, -30.0), 2.5, 2.5);*/
+
+ painter->setBrush(m_penColor);
+ painter->setPen(QPen(m_penColor, 2.5, Qt::SolidLine, Qt::RoundCap));
+
+ // eyes
+ if (m_isDead) {
+ painter->drawLine(-30.0, -30.0, -20.0, -20.0);
+ painter->drawLine(-20.0, -30.0, -30.0, -20.0);
+
+ painter->drawLine(20.0, -30.0, 30.0, -20.0);
+ painter->drawLine(30.0, -30.0, 20.0, -20.0);
+ } else {
+ painter->drawChord(QRectF(-30.0, -30.0, 25.0, 70.0), 30.0*16, 120.0*16);
+ painter->drawChord(QRectF(5.0, -30.0, 25.0, 70.0), 30.0*16, 120.0*16);
+ }
+
+ // mouth
+ if (m_isDead) {
+ painter->drawLine(-28.0, 2.0, 29.0, 2.0);
+ } else {
+ painter->setBrush(QColor(128, 0, 64 ));
+ painter->drawChord(QRectF(-28.0, 2.0-55.0/2.0, 57.0, 55.0), 0.0, -180.0*16);
+ }
+
+ // pupils
+ if (!m_isDead) {
+ painter->setPen(QPen(m_fillColor, 1.0, Qt::SolidLine, Qt::RoundCap));
+ painter->setBrush(m_fillColor);
+ painter->drawEllipse(QPointF(-12.0, -25.0), 5.0, 5.0);
+ painter->drawEllipse(QPointF(22.0, -25.0), 5.0, 5.0);
+ }
+
+
+ painter->restore();
+ }
+ }
+}
+
+
+
diff --git a/examples/animation/stickman/stickman.h b/examples/animation/stickman/stickman.h
new file mode 100644
index 0000000..ae406ca
--- /dev/null
+++ b/examples/animation/stickman/stickman.h
@@ -0,0 +1,59 @@
+#ifndef STICKMAN_H
+#define STICKMAN_H
+
+#include <QGraphicsItem>
+
+const int LimbCount = 16;
+
+class Node;
+class QTimer;
+class StickMan: public QObject, public QGraphicsItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor penColor WRITE setPenColor READ penColor)
+ Q_PROPERTY(QColor fillColor WRITE setFillColor READ fillColor)
+ Q_PROPERTY(bool isDead WRITE setIsDead READ isDead)
+public:
+ StickMan();
+ ~StickMan();
+
+ virtual QRectF boundingRect() const;
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+ int nodeCount() const;
+ Node *node(int idx) const;
+
+ void setDrawSticks(bool on);
+ bool drawSticks() const { return m_sticks; }
+
+ QColor penColor() const { return m_penColor; }
+ void setPenColor(const QColor &color) { m_penColor = color; }
+
+ QColor fillColor() const { return m_fillColor; }
+ void setFillColor(const QColor &color) { m_fillColor = color; }
+
+ bool isDead() const { return m_isDead; }
+ void setIsDead(bool isDead) { m_isDead = isDead; }
+
+public slots:
+ void stabilize();
+
+protected:
+ void timerEvent(QTimerEvent *e);
+
+private:
+ QPointF posFor(int idx) const;
+
+ Node **m_nodes;
+ qreal *m_perfectBoneLengths;
+
+ uint m_sticks : 1;
+ uint m_isDead : 1;
+ uint m_reserved : 30;
+
+ QPixmap m_pixmap;
+ QColor m_penColor;
+ QColor m_fillColor;
+};
+
+#endif // STICKMAN_H
diff --git a/examples/animation/stickman/stickman.pro b/examples/animation/stickman/stickman.pro
new file mode 100644
index 0000000..136cb44
--- /dev/null
+++ b/examples/animation/stickman/stickman.pro
@@ -0,0 +1,12 @@
+######################################################################
+# Automatically generated by qmake (2.01a) ti 3. feb 19:50:14 2009
+######################################################################
+
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+HEADERS += stickman.h animation.h node.h lifecycle.h graphicsview.h
+SOURCES += main.cpp stickman.cpp animation.cpp node.cpp lifecycle.cpp graphicsview.cpp
diff --git a/examples/animation/sub-attaq/animationmanager.cpp b/examples/animation/sub-attaq/animationmanager.cpp
new file mode 100644
index 0000000..9f99426
--- /dev/null
+++ b/examples/animation/sub-attaq/animationmanager.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//Own
+#include "animationmanager.h"
+
+//Qt
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qabstractanimation.h"
+#else
+# include <QtCore/QAbstractAnimation>
+#endif
+#include <QDebug>
+
+// the universe's only animation manager
+AnimationManager *AnimationManager::instance = 0;
+
+AnimationManager::AnimationManager()
+{
+}
+
+AnimationManager *AnimationManager::self()
+{
+ if (!instance)
+ instance = new AnimationManager;
+ return instance;
+}
+
+void AnimationManager::registerAnimation(QAbstractAnimation *anim)
+{
+ animations.append(anim);
+}
+
+void AnimationManager::unregisterAnimation(QAbstractAnimation *anim)
+{
+ animations.removeAll(anim);
+}
+
+void AnimationManager::unregisterAllAnimations()
+{
+ animations.clear();
+}
+
+void AnimationManager::pauseAll()
+{
+ foreach (QAbstractAnimation* animation, animations)
+ {
+ if (animation->state() == QAbstractAnimation::Running)
+ animation->pause();
+ }
+}
+void AnimationManager::resumeAll()
+{
+ foreach (QAbstractAnimation* animation, animations)
+ {
+ if (animation->state() == QAbstractAnimation::Paused)
+ animation->resume();
+ }
+}
diff --git a/examples/animation/sub-attaq/animationmanager.h b/examples/animation/sub-attaq/animationmanager.h
new file mode 100644
index 0000000..fe92680
--- /dev/null
+++ b/examples/animation/sub-attaq/animationmanager.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ANIMATIONMANAGER_H
+#define ANIMATIONMANAGER_H
+
+#include <QObject>
+
+class QAbstractAnimation;
+
+class AnimationManager : public QObject
+{
+Q_OBJECT
+public:
+ AnimationManager();
+ void registerAnimation(QAbstractAnimation *anim);
+ void unregisterAnimation(QAbstractAnimation *anim);
+ void unregisterAllAnimations();
+ static AnimationManager *self();
+
+public slots:
+ void pauseAll();
+ void resumeAll();
+
+private:
+ static AnimationManager *instance;
+ QList<QAbstractAnimation *> animations;
+};
+
+#endif // ANIMATIONMANAGER_H
diff --git a/examples/animation/sub-attaq/boat.cpp b/examples/animation/sub-attaq/boat.cpp
new file mode 100644
index 0000000..6824f17
--- /dev/null
+++ b/examples/animation/sub-attaq/boat.cpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//Own
+#include "boat.h"
+#include "boat_p.h"
+#include "bomb.h"
+#include "pixmapitem.h"
+#include "graphicsscene.h"
+#include "animationmanager.h"
+#include "custompropertyanimation.h"
+
+//Qt
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qpropertyanimation.h"
+# include "qstatemachine.h"
+# include "qhistorystate.h"
+# include "qfinalstate.h"
+# include "qstate.h"
+#include "qsequentialanimationgroup.h"
+#include "qanimationstate.h"
+#else
+#include <QPropertyAnimation>
+#include <QStateMachine>
+#include <QHistoryState>
+#include <QFinalState>
+#include <QState>
+#include <QSequentialAnimationGroup>
+#include <QAnimationState>
+#endif
+
+static QAbstractAnimation *setupDestroyAnimation(Boat *boat)
+{
+ QSequentialAnimationGroup *group = new QSequentialAnimationGroup(boat);
+#if QT_VERSION >=0x040500
+ PixmapItem *step1 = new PixmapItem(QString("explosion/boat/step1"),GraphicsScene::Big, boat);
+ step1->setZValue(6);
+ PixmapItem *step2 = new PixmapItem(QString("explosion/boat/step2"),GraphicsScene::Big, boat);
+ step2->setZValue(6);
+ PixmapItem *step3 = new PixmapItem(QString("explosion/boat/step3"),GraphicsScene::Big, boat);
+ step3->setZValue(6);
+ PixmapItem *step4 = new PixmapItem(QString("explosion/boat/step4"),GraphicsScene::Big, boat);
+ step4->setZValue(6);
+ step1->setOpacity(0);
+ step2->setOpacity(0);
+ step3->setOpacity(0);
+ step4->setOpacity(0);
+ CustomPropertyAnimation *anim1 = new CustomPropertyAnimation(boat);
+ anim1->setMemberFunctions((QGraphicsItem*)step1, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity);
+ anim1->setDuration(100);
+ anim1->setEndValue(1);
+ CustomPropertyAnimation *anim2 = new CustomPropertyAnimation(boat);
+ anim2->setMemberFunctions((QGraphicsItem*)step2, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity);
+ anim2->setDuration(100);
+ anim2->setEndValue(1);
+ CustomPropertyAnimation *anim3 = new CustomPropertyAnimation(boat);
+ anim3->setMemberFunctions((QGraphicsItem*)step3, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity);
+ anim3->setDuration(100);
+ anim3->setEndValue(1);
+ CustomPropertyAnimation *anim4 = new CustomPropertyAnimation(boat);
+ anim4->setMemberFunctions((QGraphicsItem*)step4, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity);
+ anim4->setDuration(100);
+ anim4->setEndValue(1);
+ group->addAnimation(anim1);
+ group->addAnimation(anim2);
+ group->addAnimation(anim3);
+ group->addAnimation(anim4);
+#else
+ // work around for a bug where we don't transition if the duration is zero.
+ QtPauseAnimation *anim = new QtPauseAnimation(group);
+ anim->setDuration(1);
+ group->addAnimation(anim);
+#endif
+ AnimationManager::self()->registerAnimation(group);
+ return group;
+}
+
+
+
+Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags)
+ : QGraphicsWidget(parent,wFlags), speed(0), bombsAlreadyLaunched(0), direction(Boat::None), movementAnimation(0)
+{
+ pixmapItem = new PixmapItem(QString("boat"),GraphicsScene::Big, this);
+ setZValue(4);
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsFocusable);
+ resize(pixmapItem->boundingRect().size());
+
+ //The movement animation used to animate the boat
+ movementAnimation = new QPropertyAnimation(this, "pos");
+ AnimationManager::self()->registerAnimation(movementAnimation);
+
+ //We setup the state machien of the boat
+ QStateMachine *machine = new QStateMachine(this);
+ QState *moving = new QState(machine->rootState());
+ StopState *stopState = new StopState(this,moving);
+ machine->setInitialState(moving);
+ moving->setInitialState(stopState);
+ MoveStateRight *moveStateRight = new MoveStateRight(this,moving);
+ MoveStateLeft *moveStateLeft = new MoveStateLeft(this,moving);
+ LaunchStateRight *launchStateRight = new LaunchStateRight(this,machine->rootState());
+ LaunchStateLeft *launchStateLeft = new LaunchStateLeft(this,machine->rootState());
+
+ //then setup the transitions for the rightMove state
+ KeyStopTransition *leftStopRight = new KeyStopTransition(this,QEvent::KeyPress,Qt::Key_Left);
+ leftStopRight->setTargetState(stopState);
+ KeyMoveTransition *leftMoveRight = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Left);
+ leftMoveRight->setTargetState(moveStateRight);
+ KeyMoveTransition *rightMoveRight = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Right);
+ rightMoveRight->setTargetState(moveStateRight);
+ KeyMoveTransition *rightMoveStop = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Right);
+ rightMoveStop->setTargetState(moveStateRight);
+
+ //then setup the transitions for the leftMove state
+ KeyStopTransition *rightStopLeft = new KeyStopTransition(this,QEvent::KeyPress,Qt::Key_Right);
+ rightStopLeft->setTargetState(stopState);
+ KeyMoveTransition *rightMoveLeft = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Right);
+ rightMoveLeft->setTargetState(moveStateLeft);
+ KeyMoveTransition *leftMoveLeft = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Left);
+ leftMoveLeft->setTargetState(moveStateLeft);
+ KeyMoveTransition *leftMoveStop = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Left);
+ leftMoveStop->setTargetState(moveStateLeft);
+
+ //We set up the right move state
+ moveStateRight->addTransition(leftStopRight);
+ moveStateRight->addTransition(leftMoveRight);
+ moveStateRight->addTransition(rightMoveRight);
+ stopState->addTransition(rightMoveStop);
+
+ //We set up the left move state
+ moveStateLeft->addTransition(rightStopLeft);
+ moveStateLeft->addTransition(leftMoveLeft);
+ moveStateLeft->addTransition(rightMoveLeft);
+ stopState->addTransition(leftMoveStop);
+
+ //The animation is finished, it means we reached the border of the screen, the boat is stopped so we move to the stop state
+ moveStateLeft->addTransition(movementAnimation, SIGNAL(finished()), stopState);
+ moveStateRight->addTransition(movementAnimation, SIGNAL(finished()), stopState);
+
+ //We set up the keys for dropping bombs
+ KeyLaunchTransition *upFireLeft = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Up);
+ upFireLeft->setTargetState(launchStateRight);
+ KeyLaunchTransition *upFireRight = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Up);
+ upFireRight->setTargetState(launchStateRight);
+ KeyLaunchTransition *upFireStop = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Up);
+ upFireStop->setTargetState(launchStateRight);
+ KeyLaunchTransition *downFireLeft = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Down);
+ downFireLeft->setTargetState(launchStateLeft);
+ KeyLaunchTransition *downFireRight = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Down);
+ downFireRight->setTargetState(launchStateLeft);
+ KeyLaunchTransition *downFireMove = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Down);
+ downFireMove->setTargetState(launchStateLeft);
+
+ //We set up transitions for fire up
+ moveStateRight->addTransition(upFireRight);
+ moveStateLeft->addTransition(upFireLeft);
+ stopState->addTransition(upFireStop);
+
+ //We set up transitions for fire down
+ moveStateRight->addTransition(downFireRight);
+ moveStateLeft->addTransition(downFireLeft);
+ stopState->addTransition(downFireMove);
+
+ //Finally the launch state should come back to its original state
+ QHistoryState *historyState = moving->addHistoryState();
+ launchStateLeft->addTransition(historyState);
+ launchStateRight->addTransition(historyState);
+
+ QFinalState *final = new QFinalState(machine->rootState());
+
+ //This state play the destroyed animation
+ QAnimationState *destroyedState = new QAnimationState(machine->rootState());
+ destroyedState->addAnimation(setupDestroyAnimation(this));
+
+ //Play a nice animation when the boat is destroyed
+ moving->addTransition(this, SIGNAL(boatDestroyed()),destroyedState);
+
+ //Transition to final state when the destroyed animation is finished
+ destroyedState->addFinishedTransition(final);
+
+ //The machine has finished to be executed, then the boat is dead
+ connect(machine,SIGNAL(finished()),this, SIGNAL(boatExecutionFinished()));
+
+ machine->start();
+}
+
+void Boat::updateBoatMovement()
+{
+ if (speed == 0 || direction == Boat::None) {
+ movementAnimation->stop();
+ return;
+ }
+
+ movementAnimation->stop();
+ movementAnimation->setStartValue(pos());
+
+ if (direction == Boat::Left) {
+ movementAnimation->setEndValue(QPointF(0,y()));
+ movementAnimation->setDuration(x()/speed*15);
+ }
+ else /*if (direction == Boat::Right)*/ {
+ movementAnimation->setEndValue(QPointF(scene()->width()-size().width(),y()));
+ movementAnimation->setDuration((scene()->width()-size().width()-x())/speed*15);
+ }
+ movementAnimation->start();
+}
+
+void Boat::destroy()
+{
+ movementAnimation->stop();
+ emit boatDestroyed();
+}
+
+int Boat::bombsLaunched() const
+{
+ return bombsAlreadyLaunched;
+}
+
+void Boat::setBombsLaunched(int number)
+{
+ if (number > MAX_BOMB) {
+ qWarning("Boat::setBombsLaunched : It impossible to launch that number of bombs");
+ return;
+ }
+ bombsAlreadyLaunched = number;
+}
+
+int Boat::currentSpeed() const
+{
+ return speed;
+}
+
+void Boat::setCurrentSpeed(int speed)
+{
+ if (speed > 3 || speed < 0) {
+ qWarning("Boat::setCurrentSpeed: The boat can't run on that speed");
+ return;
+ }
+ this->speed = speed;
+}
+
+enum Boat::Movement Boat::currentDirection() const
+{
+ return direction;
+}
+
+void Boat::setCurrentDirection(Movement direction)
+{
+ this->direction = direction;
+}
+
+int Boat::type() const
+{
+ return Type;
+}
diff --git a/examples/animation/sub-attaq/boat.h b/examples/animation/sub-attaq/boat.h
new file mode 100644
index 0000000..4c4a737
--- /dev/null
+++ b/examples/animation/sub-attaq/boat.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __BOAT__H__
+#define __BOAT__H__
+
+//Qt
+#include <QObject>
+#include <QKeyEvent>
+
+#include <QDebug>
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qgraphicswidget.h"
+#else
+# include <QtGui/QGraphicsWidget>
+#endif
+
+class PixmapItem;
+class Bomb;
+class QVariantAnimation;
+
+class Boat : public QGraphicsWidget
+{
+Q_OBJECT
+Q_PROPERTY(QPointF pos READ pos WRITE setPos)
+public:
+ enum Movement {
+ None = 0,
+ Left,
+ Right
+ };
+ enum { Type = UserType + 2 };
+ Boat(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
+ void destroy();
+
+ int bombsLaunched() const;
+ void setBombsLaunched(int number);
+
+ int currentSpeed() const;
+ void setCurrentSpeed(int speed);
+
+ enum Movement currentDirection() const;
+ void setCurrentDirection(Movement direction);
+
+ void updateBoatMovement();
+
+ virtual int type() const;
+
+Q_SIGNALS:
+ void boatDestroyed();
+ void boatExecutionFinished();
+
+private:
+ int speed;
+ int bombsAlreadyLaunched;
+ Movement direction;
+ QVariantAnimation *movementAnimation;
+ PixmapItem *pixmapItem;
+};
+
+#endif //__BOAT__H__
diff --git a/examples/animation/sub-attaq/boat_p.h b/examples/animation/sub-attaq/boat_p.h
new file mode 100644
index 0000000..8dacaba
--- /dev/null
+++ b/examples/animation/sub-attaq/boat_p.h
@@ -0,0 +1,258 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BOAT_P_H
+#define BOAT_P_H
+
+//Own
+#include "bomb.h"
+#include "graphicsscene.h"
+
+// Qt
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qkeyeventtransition.h"
+#else
+# include <QtGui/QKeyEventTransition>
+#endif
+
+static const int MAX_BOMB = 5;
+
+
+//These transtion test if we have to stop the boat (i.e current speed is 1)
+class KeyStopTransition : public QKeyEventTransition
+{
+public:
+ KeyStopTransition(Boat *boat, QEvent::Type type, int key)
+ : QKeyEventTransition(boat,type, key)
+ {
+ this->boat = boat;
+ this->key = key;
+#if defined(Q_OS_MAC)
+ setModifiers(Qt::KeypadModifier);
+#endif
+ }
+protected:
+ virtual bool eventTest(QEvent *event) const
+ {
+ Q_UNUSED(event);
+ if (!QKeyEventTransition::eventTest(event))
+ return false;
+ if (boat->currentSpeed() == 1)
+ return true;
+ else
+ return false;
+ }
+private:
+ Boat * boat;
+ int key;
+};
+
+//These transtion test if we have to move the boat (i.e current speed was 0 or another value)
+ class KeyMoveTransition : public QKeyEventTransition
+{
+public:
+ KeyMoveTransition(Boat *boat, QEvent::Type type, int key)
+ : QKeyEventTransition(boat,type, key)
+ {
+ this->boat = boat;
+ this->key = key;
+#if defined(Q_OS_MAC)
+ setModifiers(Qt::KeypadModifier);
+#endif
+ }
+protected:
+ virtual bool eventTest(QEvent *event) const
+ {
+ Q_UNUSED(event);
+ if (!QKeyEventTransition::eventTest(event))
+ return false;
+ if (boat->currentSpeed() >= 0)
+ return true;
+ else
+ return false;
+
+ }
+ void onTransition()
+ {
+ //We decrease the speed if needed
+ if (key == Qt::Key_Left && boat->currentDirection() == Boat::Right)
+ boat->setCurrentSpeed(boat->currentSpeed() - 1);
+ else if (key == Qt::Key_Right && boat->currentDirection() == Boat::Left)
+ boat->setCurrentSpeed(boat->currentSpeed() - 1);
+ else if (boat->currentSpeed() < 3)
+ boat->setCurrentSpeed(boat->currentSpeed() + 1);
+ boat->updateBoatMovement();
+ }
+private:
+ Boat * boat;
+ int key;
+};
+
+//This transition trigger the bombs launch
+ class KeyLaunchTransition : public QKeyEventTransition
+{
+public:
+ KeyLaunchTransition(Boat *boat, QEvent::Type type, int key)
+ : QKeyEventTransition(boat,type, key)
+ {
+ this->boat = boat;
+ this->key = key;
+#if defined(Q_OS_MAC)
+ setModifiers(Qt::KeypadModifier);
+#endif
+ }
+protected:
+ virtual bool eventTest(QEvent *event) const
+ {
+ Q_UNUSED(event);
+ if (!QKeyEventTransition::eventTest(event))
+ return false;
+ //We have enough bomb?
+ if (boat->bombsLaunched() < MAX_BOMB)
+ return true;
+ else
+ return false;
+ }
+private:
+ Boat * boat;
+ int key;
+};
+
+//This state is describing when the boat is moving right
+class MoveStateRight : public QState
+{
+public:
+ MoveStateRight(Boat *boat,QState *parent = 0) : QState(parent)
+ {
+ this->boat = boat;
+ }
+protected:
+ void onEntry()
+ {
+ boat->setCurrentDirection(Boat::Right);
+ boat->updateBoatMovement();
+ }
+private:
+ Boat * boat;
+};
+
+ //This state is describing when the boat is moving left
+class MoveStateLeft : public QState
+{
+public:
+ MoveStateLeft(Boat *boat,QState *parent = 0) : QState(parent)
+ {
+ this->boat = boat;
+ }
+protected:
+ void onEntry()
+ {
+ boat->setCurrentDirection(Boat::Left);
+ boat->updateBoatMovement();
+ }
+private:
+ Boat * boat;
+};
+
+//This state is describing when the boat is in a stand by position
+class StopState : public QState
+{
+public:
+ StopState(Boat *boat,QState *parent = 0) : QState(parent)
+ {
+ this->boat = boat;
+ }
+protected:
+ void onEntry()
+ {
+ boat->setCurrentSpeed(0);
+ boat->setCurrentDirection(Boat::None);
+ boat->updateBoatMovement();
+ }
+private:
+ Boat * boat;
+};
+
+//This state is describing the launch of the torpedo on the right
+class LaunchStateRight : public QState
+{
+public:
+ LaunchStateRight(Boat *boat,QState *parent = 0) : QState(parent)
+ {
+ this->boat = boat;
+ }
+protected:
+ void onEntry()
+ {
+ Bomb *b = new Bomb();
+ b->setPos(boat->x()+boat->size().width(),boat->y());
+ GraphicsScene *scene = static_cast<GraphicsScene *>(boat->scene());
+ scene->addItem(b);
+ b->launch(Bomb::Right);
+ boat->setBombsLaunched(boat->bombsLaunched() + 1);
+ }
+private:
+ Boat * boat;
+};
+
+//This state is describing the launch of the torpedo on the left
+class LaunchStateLeft : public QState
+{
+public:
+ LaunchStateLeft(Boat *boat,QState *parent = 0) : QState(parent)
+ {
+ this->boat = boat;
+ }
+protected:
+ void onEntry()
+ {
+ Bomb *b = new Bomb();
+ b->setPos(boat->x() - b->size().width(), boat->y());
+ GraphicsScene *scene = static_cast<GraphicsScene *>(boat->scene());
+ scene->addItem(b);
+ b->launch(Bomb::Left);
+ boat->setBombsLaunched(boat->bombsLaunched() + 1);
+ }
+private:
+ Boat * boat;
+};
+
+#endif // BOAT_P_H
diff --git a/examples/animation/sub-attaq/bomb.cpp b/examples/animation/sub-attaq/bomb.cpp
new file mode 100644
index 0000000..b6ae5a3
--- /dev/null
+++ b/examples/animation/sub-attaq/bomb.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//Own
+#include "bomb.h"
+#include "submarine.h"
+#include "pixmapitem.h"
+#include "animationmanager.h"
+
+//Qt
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+#include "qpropertyanimation.h"
+#include "qsequentialanimationgroup.h"
+#include "qanimationstate.h"
+#include "qstatemachine.h"
+#include "qfinalstate.h"
+#else
+#include <QtCore/QSequentialAnimationGroup>
+#include <QtCore/QPropertyAnimation>
+#include <QtCore/QAnimationState>
+#include <QtCore/QStateMachine>
+#include <QtCore/QFinalState>
+#endif
+
+Bomb::Bomb(QGraphicsItem * parent, Qt::WindowFlags wFlags)
+ : QGraphicsWidget(parent,wFlags), launchAnimation(0)
+{
+ pixmapItem = new PixmapItem(QString("bomb"),GraphicsScene::Big, this);
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ setFlags(QGraphicsItem::ItemIsMovable);
+ setZValue(2);
+ resize(pixmapItem->boundingRect().size());
+}
+
+void Bomb::launch(Bomb::Direction direction)
+{
+ launchAnimation = new QSequentialAnimationGroup();
+ AnimationManager::self()->registerAnimation(launchAnimation);
+ qreal delta = direction == Right ? 20 : - 20;
+ QPropertyAnimation *anim = new QPropertyAnimation(this, "pos");
+ anim->setEndValue(QPointF(x() + delta,y() - 20));
+ anim->setDuration(150);
+ launchAnimation->addAnimation(anim);
+ anim = new QPropertyAnimation(this, "pos");
+ anim->setEndValue(QPointF(x() + delta*2, y() ));
+ anim->setDuration(150);
+ launchAnimation->addAnimation(anim);
+ anim = new QPropertyAnimation(this, "pos");
+ anim->setEndValue(QPointF(x() + delta*2,scene()->height()));
+ anim->setDuration(y()/2*60);
+ launchAnimation->addAnimation(anim);
+ connect(anim,SIGNAL(valueChanged(const QVariant &)),this,SLOT(onAnimationLaunchValueChanged(const QVariant &)));
+
+ //We setup the state machine of the bomb
+ QStateMachine *machine = new QStateMachine(this);
+
+ //This state is when the launch animation is playing
+ QAnimationState *launched = new QAnimationState(launchAnimation,machine->rootState());
+
+ machine->setInitialState(launched);
+
+ //End
+ QFinalState *final = new QFinalState(machine->rootState());
+
+ //### Add a nice animation when the bomb is destroyed
+ launched->addTransition(this, SIGNAL(bombExplosed()),final);
+
+ //If the animation is finished, then we move to the final state
+ launched->addFinishedTransition(final);
+
+ //The machine has finished to be executed, then the boat is dead
+ connect(machine,SIGNAL(finished()),this, SIGNAL(bombExecutionFinished()));
+
+ machine->start();
+
+}
+
+void Bomb::onAnimationLaunchValueChanged(const QVariant &)
+{
+ foreach (QGraphicsItem * item , collidingItems(Qt::IntersectsItemBoundingRect)) {
+ if (item->type() == SubMarine::Type) {
+ SubMarine *s = static_cast<SubMarine *>(item);
+ destroy();
+ s->destroy();
+ }
+ }
+}
+
+void Bomb::destroy()
+{
+ launchAnimation->stop();
+ emit bombExplosed();
+}
diff --git a/examples/animation/sub-attaq/bomb.h b/examples/animation/sub-attaq/bomb.h
new file mode 100644
index 0000000..9191e6e
--- /dev/null
+++ b/examples/animation/sub-attaq/bomb.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __BOMB__H__
+#define __BOMB__H__
+
+//Qt
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qanimationgroup.h"
+# include "qgraphicswidget.h"
+#else
+# include <QtGui/QGraphicsWidget>
+# include <QtCore/QAnimationGroup>
+#endif
+
+class PixmapItem;
+
+class Bomb : public QGraphicsWidget
+{
+Q_OBJECT
+Q_PROPERTY(QPointF pos READ pos WRITE setPos)
+public:
+ enum Direction {
+ Left = 0,
+ Right
+ };
+ Bomb(QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0);
+ void launch(Direction direction);
+ void destroy();
+
+Q_SIGNALS:
+ void bombExplosed();
+ void bombExecutionFinished();
+
+private slots:
+ void onAnimationLaunchValueChanged(const QVariant &);
+
+private:
+ QAnimationGroup *launchAnimation;
+ PixmapItem *pixmapItem;
+};
+
+#endif //__BOMB__H__
diff --git a/examples/animation/sub-attaq/custompropertyanimation.cpp b/examples/animation/sub-attaq/custompropertyanimation.cpp
new file mode 100644
index 0000000..45997af
--- /dev/null
+++ b/examples/animation/sub-attaq/custompropertyanimation.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "custompropertyanimation.h"
+#include "custompropertyanimation_p.h"
+
+// Qt
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+
+void CustomPropertyAnimationPrivate::initDefaultStartValue()
+{
+ if (!animProp)
+ return;
+ QVariant def = animProp->read();
+ if (def.isValid())
+ convertValues(def.userType());
+ if (animProp && !defaultStartValue.isValid()
+ && ((currentTime == 0 && (currentIteration || currentIteration == 0))
+ || (currentTime == duration && currentIteration == (iterationCount - 1)))) {
+ setDefaultStartValue(def);
+ }
+}
+
+
+CustomPropertyAnimation::CustomPropertyAnimation(QObject *parent) :
+ QVariantAnimation(*new CustomPropertyAnimationPrivate, parent)
+{
+}
+
+CustomPropertyAnimation::~CustomPropertyAnimation()
+{
+}
+
+void CustomPropertyAnimation::setProperty(AbstractProperty *animProp)
+{
+ Q_D(CustomPropertyAnimation);
+ if (d->animProp == animProp)
+ return;
+ delete d->animProp;
+ d->animProp = animProp;
+}
+
+/*!
+ \reimp
+ */
+void CustomPropertyAnimation::updateCurrentValue(const QVariant &value)
+{
+ Q_D(CustomPropertyAnimation);
+ if (!d->animProp || state() == QAbstractAnimation::Stopped)
+ return;
+
+ d->animProp->write(value);
+}
+
+
+/*!
+ \reimp
+*/
+void CustomPropertyAnimation::updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState)
+{
+ Q_D(CustomPropertyAnimation);
+ // Initialize start value
+ if (oldState == QAbstractAnimation::Stopped)
+ d->initDefaultStartValue();
+
+ QVariantAnimation::updateState(oldState, newState);
+}
+
+
+
+#include "moc_custompropertyanimation.cpp"
+
+QT_END_NAMESPACE
diff --git a/examples/animation/sub-attaq/custompropertyanimation.h b/examples/animation/sub-attaq/custompropertyanimation.h
new file mode 100644
index 0000000..ba6ef55
--- /dev/null
+++ b/examples/animation/sub-attaq/custompropertyanimation.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CUSTOMPROPERTYANIMATION_H
+#define CUSTOMPROPERTYANIMATION_H
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qvariantanimation.h"
+#else
+# include <QtCore/qvariantanimation.h>
+#endif
+
+class QGraphicsItem;
+class CustomPropertyAnimationPrivate;
+
+struct AbstractProperty
+{
+ virtual QVariant read() const = 0;
+ virtual void write(const QVariant &value) = 0;
+};
+
+
+class CustomPropertyAnimation : public QVariantAnimation
+{
+ Q_OBJECT
+
+ template <typename Target, typename T, typename T2 = T>
+ class MemberFunctionProperty : public AbstractProperty
+ {
+ public:
+ typedef T (Target::*Getter)(void) const;
+ typedef void (Target::*Setter)(T2);
+
+ MemberFunctionProperty(Target* target, Getter getter, Setter setter)
+ : m_target(target), m_getter(getter), m_setter(setter) {}
+
+ virtual void write(const QVariant &value)
+ {
+ if (m_setter) (m_target->*m_setter)(qVariantValue<T>(value));
+ }
+
+ virtual QVariant read() const
+ {
+ if (m_getter) return qVariantFromValue<T>((m_target->*m_getter)());
+ return QVariant();
+ }
+
+ private:
+ Target *m_target;
+ Getter m_getter;
+ Setter m_setter;
+ };
+
+public:
+ CustomPropertyAnimation(QObject *parent = 0);
+ ~CustomPropertyAnimation();
+
+ template<class Target, typename T>
+ void setMemberFunctions(Target* target, T (Target::*getter)() const, void (Target::*setter)(const T& ))
+ {
+ setProperty(new MemberFunctionProperty<Target, T, const T&>(target, getter, setter));
+ }
+
+ template<class Target, typename T>
+ void setMemberFunctions(Target* target, T (Target::*getter)() const, void (Target::*setter)(T))
+ {
+ setProperty(new MemberFunctionProperty<Target, T>(target, getter, setter));
+ }
+
+ void updateCurrentValue(const QVariant &value);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void setProperty(AbstractProperty *animProp);
+
+private:
+ Q_DISABLE_COPY(CustomPropertyAnimation);
+ Q_DECLARE_PRIVATE(CustomPropertyAnimation);
+};
+
+#endif // CUSTOMPROPERTYANIMATION_H
diff --git a/examples/animation/sub-attaq/custompropertyanimation_p.h b/examples/animation/sub-attaq/custompropertyanimation_p.h
new file mode 100644
index 0000000..89fc757
--- /dev/null
+++ b/examples/animation/sub-attaq/custompropertyanimation_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CUSTOMPROPERTYANIMATION_P_H
+#define CUSTOMPROPERTYANIMATION_P_H
+
+#ifdef QT_EXPERIMENTAL_SOLUTION
+# include "qvariantanimation_p.h"
+#else
+# include <private/qvariantanimation_p.h>
+#endif
+
+class CustomPropertyAnimationPrivate : public QVariantAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(CustomPropertyAnimation)
+public:
+ CustomPropertyAnimationPrivate() : QVariantAnimationPrivate(), animProp(0)
+ {
+ }
+
+ void initDefaultStartValue();
+
+ AbstractProperty *animProp;
+};
+
+#endif //QTCUSTOMPROPERTYANIMATION_P_H
diff --git a/examples/animation/sub-attaq/data.xml b/examples/animation/sub-attaq/data.xml
new file mode 100644
index 0000000..41d4754
--- /dev/null
+++ b/examples/animation/sub-attaq/data.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<subattaq>
+ <submarines>
+ <submarine type="0" points="10" name="Q1" />
+ <submarine type="1" points="20" name="Q2" />
+ </submarines>
+ <levels>
+ <level id="0" name="Seaman recruit">
+ <subinstance type="0" nb="2"/>
+ </level>
+ <level id="1" name="Seaman apprentice">
+ <subinstance type="0" nb="4"/>
+ </level>
+ </levels>
+</subattaq>
diff --git a/examples/animation/sub-attaq/graphicsscene.cpp b/examples/animation/sub-attaq/graphicsscene.cpp
new file mode 100644
index 0000000..a7f4c1b
--- /dev/null
+++ b/examples/animation/sub-attaq/graphicsscene.cpp
@@ -0,0 +1,368 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//Own
+#include "graphicsscene.h"
+#include "states.h"
+#include "boat.h"
+#include "submarine.h"
+#include "torpedo.h"
+#include "bomb.h"
+#include "pixmapitem.h"
+#include "custompropertyanimation.h"
+#include "animationmanager.h"
+
+//Qt
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+#include "qpropertyanimation.h"
+#include "qsequentialanimationgroup.h"
+#include "qparallelanimationgroup.h"
+#include "qstatemachine.h"
+#include "qanimationstate.h"
+#include "qfinalstate.h"
+#include "qpauseanimation.h"
+#else
+#include <QPropertyAnimation>
+#include <QSequentialAnimationGroup>
+#include <QParallelAnimationGroup>
+#include <QStateMachine>
+#include <QAnimationState>
+#include <QFinalState>
+#include <QPauseAnimation>
+#endif
+#include <QAction>
+#include <QDir>
+#include <QApplication>
+#include <QMessageBox>
+#include <QGraphicsView>
+#include <QGraphicsSceneMouseEvent>
+#include <QXmlStreamReader>
+
+//helper function that creates an animation for position and inserts it into group
+static CustomPropertyAnimation *addGraphicsItemPosAnimation(QSequentialAnimationGroup *group,
+ QGraphicsItem *item, const QPointF &endPos)
+{
+ CustomPropertyAnimation *ret = new CustomPropertyAnimation(group);
+ ret->setMemberFunctions(item, &QGraphicsItem::pos, &QGraphicsItem::setPos);
+ ret->setEndValue(endPos);
+ ret->setDuration(200);
+ ret->setEasingCurve(QEasingCurve::OutElastic);
+ group->addPause(50);
+ return ret;
+}
+
+//helper function that creates an animation for opacity and inserts it into group
+static void addGraphicsItemFadeoutAnimation(QAnimationGroup *group, QGraphicsItem *item)
+{
+#if QT_VERSION >=0x040500
+ CustomPropertyAnimation *anim = new CustomPropertyAnimation(group);
+ anim->setMemberFunctions(item, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity);
+ anim->setDuration(800);
+ anim->setEndValue(0);
+ anim->setEasingCurve(QEasingCurve::OutQuad);
+#else
+ // work around for a bug where we don't transition if the duration is zero.
+ QtPauseAnimation *anim = new QtPauseAnimation(group);
+ anim->setDuration(1);
+#endif
+}
+
+GraphicsScene::GraphicsScene(int x, int y, int width, int height, Mode mode)
+ : QGraphicsScene(x,y,width,height), mode(mode), newAction(0), quitAction(0), boat(0)
+{
+ backgroundItem = new PixmapItem(QString("background"),mode);
+ backgroundItem->setZValue(1);
+ backgroundItem->setPos(0,0);
+ addItem(backgroundItem);
+
+ PixmapItem *surfaceItem = new PixmapItem(QString("surface"),mode);
+ surfaceItem->setZValue(3);
+ surfaceItem->setPos(0,sealLevel() - surfaceItem->boundingRect().height()/2);
+ addItem(surfaceItem);
+
+ //parse the xml that contain all data of the game
+ QXmlStreamReader reader;
+ QFile file(QDir::currentPath() + "/data.xml");
+ file.open(QIODevice::ReadOnly);
+ reader.setDevice(&file);
+ LevelDescription currentLevel;
+ while (!reader.atEnd()) {
+ reader.readNext();
+ if (reader.tokenType() == QXmlStreamReader::StartElement) {
+ if (reader.name() == "submarine")
+ {
+ SubmarineDescription desc;
+ desc.name = reader.attributes().value("name").toString();
+ desc.points = reader.attributes().value("points").toString().toInt();
+ desc.type = reader.attributes().value("type").toString().toInt();
+ submarinesData.append(desc);
+ }
+ if (reader.name() == "level")
+ {
+ currentLevel.id = reader.attributes().value("id").toString().toInt();
+ currentLevel.name = reader.attributes().value("name").toString();
+ }
+ if (reader.name() == "subinstance")
+ {
+ currentLevel.submarines.append(qMakePair(reader.attributes().value("type").toString().toInt(),reader.attributes().value("nb").toString().toInt()));
+ }
+ }
+ if (reader.tokenType() == QXmlStreamReader::EndElement) {
+ if (reader.name() == "level")
+ {
+ levelsData.insert(currentLevel.id,currentLevel);
+ currentLevel.submarines.clear();
+ }
+ }
+ }
+}
+
+qreal GraphicsScene::sealLevel() const
+{
+ if (mode == Big)
+ return 220;
+ else
+ return 160;
+}
+
+void GraphicsScene::setupScene(const QList<QAction *> &actions)
+{
+ newAction = actions.at(0);
+ quitAction = actions.at(1);
+
+ QGraphicsItem *logo_s = addWelcomeItem(QPixmap(":/logo-s"));
+ QGraphicsItem *logo_u = addWelcomeItem(QPixmap(":/logo-u"));
+ QGraphicsItem *logo_b = addWelcomeItem(QPixmap(":/logo-b"));
+ QGraphicsItem *logo_dash = addWelcomeItem(QPixmap(":/logo-dash"));
+ QGraphicsItem *logo_a = addWelcomeItem(QPixmap(":/logo-a"));
+ QGraphicsItem *logo_t = addWelcomeItem(QPixmap(":/logo-t"));
+ QGraphicsItem *logo_t2 = addWelcomeItem(QPixmap(":/logo-t2"));
+ QGraphicsItem *logo_a2 = addWelcomeItem(QPixmap(":/logo-a2"));
+ QGraphicsItem *logo_q = addWelcomeItem(QPixmap(":/logo-q"));
+ QGraphicsItem *logo_excl = addWelcomeItem(QPixmap(":/logo-excl"));
+ logo_s->setZValue(3);
+ logo_u->setZValue(4);
+ logo_b->setZValue(5);
+ logo_dash->setZValue(6);
+ logo_a->setZValue(7);
+ logo_t->setZValue(8);
+ logo_t2->setZValue(9);
+ logo_a2->setZValue(10);
+ logo_q->setZValue(11);
+ logo_excl->setZValue(12);
+ logo_s->setPos(QPointF(-1000, -1000));
+ logo_u->setPos(QPointF(-800, -1000));
+ logo_b->setPos(QPointF(-600, -1000));
+ logo_dash->setPos(QPointF(-400, -1000));
+ logo_a->setPos(QPointF(1000, 2000));
+ logo_t->setPos(QPointF(800, 2000));
+ logo_t2->setPos(QPointF(600, 2000));
+ logo_a2->setPos(QPointF(400, 2000));
+ logo_q->setPos(QPointF(200, 2000));
+ logo_excl->setPos(QPointF(0, 2000));
+
+ QSequentialAnimationGroup * lettersGroupMoving = new QSequentialAnimationGroup(this);
+ QParallelAnimationGroup * lettersGroupFading = new QParallelAnimationGroup(this);
+
+ //creation of the animations for moving letters
+ addGraphicsItemPosAnimation(lettersGroupMoving, logo_s, QPointF(300, 150));
+ addGraphicsItemPosAnimation(lettersGroupMoving, logo_u, QPointF(350, 150));
+ addGraphicsItemPosAnimation(lettersGroupMoving, logo_b, QPointF(400, 120));
+ addGraphicsItemPosAnimation(lettersGroupMoving, logo_dash, QPointF(460, 150));
+ addGraphicsItemPosAnimation(lettersGroupMoving, logo_a, QPointF(350, 250));
+ addGraphicsItemPosAnimation(lettersGroupMoving, logo_t, QPointF(400, 250));
+ addGraphicsItemPosAnimation(lettersGroupMoving, logo_t2, QPointF(430, 250));
+ addGraphicsItemPosAnimation(lettersGroupMoving, logo_a2, QPointF(465, 250));
+ addGraphicsItemPosAnimation(lettersGroupMoving, logo_q, QPointF(510, 250));
+ addGraphicsItemPosAnimation(lettersGroupMoving, logo_excl, QPointF(570, 220));
+
+ //creation of the animations for fading out the letters
+ addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_s);
+ addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_u);
+ addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_b);
+ addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_dash);
+ addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_a);
+ addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_t);
+ addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_t2);
+ addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_a2);
+ addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_q);
+ addGraphicsItemFadeoutAnimation(lettersGroupFading, logo_excl);
+ connect(lettersGroupFading, SIGNAL(finished()), this, SLOT(onIntroAnimationFinished()));
+
+ QStateMachine *machine = new QStateMachine(this);
+
+ //This state is when the player is playing
+ PlayState *gameState = new PlayState(this,machine->rootState());
+
+ //Final state
+ QFinalState *final = new QFinalState(machine->rootState());
+
+ //Animation when the player enter in the game
+ QAnimationState *animationState = new QAnimationState(lettersGroupMoving, machine->rootState());
+ animationState->addAnimatedTransition(newAction, SIGNAL(triggered()),gameState,lettersGroupFading);
+
+ //New Game is triggered then player start playing
+ gameState->addTransition(newAction, SIGNAL(triggered()),gameState);
+
+ //Wanna quit, then connect to CTRL+Q
+ gameState->addTransition(quitAction, SIGNAL(triggered()),final);
+ animationState->addTransition(quitAction, SIGNAL(triggered()),final);
+
+ //Welcome screen is the initial state
+ machine->setInitialState(animationState);
+
+ machine->start();
+
+ //We reach the final state, then we quit
+ connect(machine,SIGNAL(finished()),this, SLOT(onQuitGameTriggered()));
+}
+
+void GraphicsScene::addItem(Bomb *bomb)
+{
+ bombs.insert(bomb);
+ connect(bomb,SIGNAL(bombExecutionFinished()),this, SLOT(onBombExecutionFinished()));
+ QGraphicsScene::addItem(bomb);
+}
+
+void GraphicsScene::addItem(Torpedo *torpedo)
+{
+ torpedos.insert(torpedo);
+ connect(torpedo,SIGNAL(torpedoExecutionFinished()),this, SLOT(onTorpedoExecutionFinished()));
+ QGraphicsScene::addItem(torpedo);
+}
+
+void GraphicsScene::addItem(SubMarine *submarine)
+{
+ submarines.insert(submarine);
+ connect(submarine,SIGNAL(subMarineExecutionFinished()),this, SLOT(onSubMarineExecutionFinished()));
+ QGraphicsScene::addItem(submarine);
+}
+
+void GraphicsScene::addItem(QGraphicsItem *item)
+{
+ QGraphicsScene::addItem(item);
+}
+
+void GraphicsScene::mousePressEvent (QGraphicsSceneMouseEvent * event)
+{
+ event->ignore();
+}
+
+void GraphicsScene::onQuitGameTriggered()
+{
+ qApp->closeAllWindows();
+}
+
+void GraphicsScene::onBombExecutionFinished()
+{
+ Bomb *bomb = qobject_cast<Bomb *>(sender());
+ bombs.remove(bomb);
+ bomb->deleteLater();
+ if (boat)
+ boat->setBombsLaunched(boat->bombsLaunched() - 1);
+}
+
+void GraphicsScene::onTorpedoExecutionFinished()
+{
+ Torpedo *torpedo = qobject_cast<Torpedo *>(sender());
+ torpedos.remove(torpedo);
+ torpedo->deleteLater();
+}
+
+void GraphicsScene::onSubMarineExecutionFinished()
+{
+ SubMarine *submarine = qobject_cast<SubMarine *>(sender());
+ submarines.remove(submarine);
+ if (submarines.count() == 0) {
+ emit allSubMarineDestroyed(submarine->points());
+ } else {
+ emit subMarineDestroyed(submarine->points());
+ }
+ submarine->deleteLater();
+}
+
+int GraphicsScene::remainingSubMarines() const
+{
+ return submarines.count();
+}
+
+void GraphicsScene::clearScene()
+{
+ foreach (SubMarine *sub,submarines) {
+ sub->destroy();
+ delete sub;
+ }
+
+ foreach (Torpedo *torpedo,torpedos) {
+ torpedo->destroy();
+ delete torpedo;
+ }
+
+ foreach (Bomb *bomb,bombs) {
+ bomb->destroy();
+ delete bomb;
+ }
+
+ submarines.clear();
+ bombs.clear();
+ torpedos.clear();
+
+ AnimationManager::self()->unregisterAllAnimations();
+
+ if (boat) {
+ delete boat;
+ boat = 0;
+ }
+}
+
+QGraphicsPixmapItem *GraphicsScene::addWelcomeItem(const QPixmap &pm)
+{
+ QGraphicsPixmapItem *item = addPixmap(pm);
+ welcomeItems << item;
+ return item;
+}
+
+void GraphicsScene::onIntroAnimationFinished()
+{
+ qDeleteAll(welcomeItems);
+ welcomeItems.clear();
+}
+
diff --git a/examples/animation/sub-attaq/graphicsscene.h b/examples/animation/sub-attaq/graphicsscene.h
new file mode 100644
index 0000000..875f59f
--- /dev/null
+++ b/examples/animation/sub-attaq/graphicsscene.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __GRAPHICSSCENE__H__
+#define __GRAPHICSSCENE__H__
+
+//Qt
+#include <QGraphicsScene>
+#include <QSet>
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qstate.h"
+#else
+# include <QState>
+#endif
+
+
+class Boat;
+class SubMarine;
+class Torpedo;
+class Bomb;
+class PixmapItem;
+class QAction;
+
+class GraphicsScene : public QGraphicsScene
+{
+Q_OBJECT
+public:
+ enum Mode {
+ Big = 0,
+ Small
+ };
+
+ struct SubmarineDescription {
+ int type;
+ int points;
+ QString name;
+ };
+
+ struct LevelDescription {
+ int id;
+ QString name;
+ QList<QPair<int,int> > submarines;
+ };
+
+ GraphicsScene(int x, int y, int width, int height, Mode mode = Big);
+ qreal sealLevel() const;
+ void setupScene(const QList<QAction *> &actions);
+ void addItem(Bomb *bomb);
+ void addItem(Torpedo *torpedo);
+ void addItem(SubMarine *submarine);
+ void addItem(QGraphicsItem *item);
+ int remainingSubMarines() const;
+ void clearScene();
+ QGraphicsPixmapItem *addWelcomeItem(const QPixmap &pm);
+
+Q_SIGNALS:
+ void subMarineDestroyed(int);
+ void allSubMarineDestroyed(int);
+
+protected:
+ void mousePressEvent (QGraphicsSceneMouseEvent * event);
+
+private slots:
+ void onQuitGameTriggered();
+ void onBombExecutionFinished();
+ void onTorpedoExecutionFinished();
+ void onSubMarineExecutionFinished();
+ void onIntroAnimationFinished();
+
+private:
+ Mode mode;
+ PixmapItem *backgroundItem;
+ QAction * newAction;
+ QAction * quitAction;
+ Boat *boat;
+ QSet<SubMarine *> submarines;
+ QSet<Bomb *> bombs;
+ QSet<Torpedo *> torpedos;
+ QVector<QGraphicsPixmapItem *> welcomeItems;
+ QVector<SubmarineDescription> submarinesData;
+ QHash<int, LevelDescription> levelsData;
+
+ friend class PauseState;
+ friend class PlayState;
+ friend class LostState;
+ friend class WinState;
+};
+
+#endif //__GRAPHICSSCENE__H__
+
diff --git a/examples/animation/sub-attaq/main.cpp b/examples/animation/sub-attaq/main.cpp
new file mode 100644
index 0000000..ffaa86f
--- /dev/null
+++ b/examples/animation/sub-attaq/main.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ Q_INIT_RESOURCE(subattaq);
+
+ qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
+
+ MainWindow w;
+ w.show();
+
+ return app.exec();
+}
diff --git a/examples/animation/sub-attaq/mainwindow.cpp b/examples/animation/sub-attaq/mainwindow.cpp
new file mode 100644
index 0000000..c25b9ef
--- /dev/null
+++ b/examples/animation/sub-attaq/mainwindow.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//Own
+#include "mainwindow.h"
+#include "graphicsscene.h"
+
+#ifndef QT_NO_OPENGL
+ #include <QtOpenGL/QtOpenGL>
+#endif
+//Qt
+#include <QGraphicsView>
+
+MainWindow::MainWindow() : QMainWindow(0)
+{
+ QMenuBar *menuBar = new QMenuBar;
+ QMenu *file = new QMenu(tr("&File"),menuBar);
+
+ QAction *newAction = new QAction(tr("New Game"),file);
+ newAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_N));
+ file->addAction(newAction);
+ QAction *quitAction = new QAction(tr("Quit"),file);
+ quitAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q));
+ file->addAction(quitAction);
+
+ menuBar->addMenu(file);
+ setMenuBar(menuBar);
+
+ QStringList list = QApplication::arguments();
+ if (list.contains("-fullscreen")) {
+ scene = new GraphicsScene(0, 0, 750, 400,GraphicsScene::Small);
+ setWindowState(Qt::WindowFullScreen);
+ } else {
+ scene = new GraphicsScene(0, 0, 880, 630);
+ layout()->setSizeConstraint(QLayout::SetFixedSize);
+ }
+
+ view = new QGraphicsView(scene,this);
+ view->setAlignment(Qt::AlignLeft | Qt::AlignTop);
+ QList<QAction *> actions;
+ actions << newAction << quitAction;
+ scene->setupScene(actions);
+#ifndef QT_NO_OPENGL
+ view->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
+#endif
+
+ setCentralWidget(view);
+
+}
+
+MainWindow::~MainWindow()
+{
+}
+
diff --git a/examples/animation/sub-attaq/mainwindow.h b/examples/animation/sub-attaq/mainwindow.h
new file mode 100644
index 0000000..6289b3f
--- /dev/null
+++ b/examples/animation/sub-attaq/mainwindow.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __MAINWINDOW__H__
+#define __MAINWINDOW__H__
+
+//Qt
+#include <QMainWindow>
+
+class GraphicsScene;
+class QGraphicsView;
+
+class MainWindow : public QMainWindow
+{
+Q_OBJECT
+public:
+ MainWindow();
+ ~MainWindow();
+
+private:
+ GraphicsScene *scene;
+ QGraphicsView *view;
+};
+
+#endif //__MAINWINDOW__H__
diff --git a/examples/animation/sub-attaq/pics/big/background.png b/examples/animation/sub-attaq/pics/big/background.png
new file mode 100644
index 0000000..9f58157
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/background.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/boat.png b/examples/animation/sub-attaq/pics/big/boat.png
new file mode 100644
index 0000000..be82dff
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/boat.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/bomb.png b/examples/animation/sub-attaq/pics/big/bomb.png
new file mode 100644
index 0000000..3af5f2f
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/bomb.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/explosion/boat/step1.png b/examples/animation/sub-attaq/pics/big/explosion/boat/step1.png
new file mode 100644
index 0000000..c9fd8b0
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/explosion/boat/step1.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/explosion/boat/step2.png b/examples/animation/sub-attaq/pics/big/explosion/boat/step2.png
new file mode 100644
index 0000000..7528f2d
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/explosion/boat/step2.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/explosion/boat/step3.png b/examples/animation/sub-attaq/pics/big/explosion/boat/step3.png
new file mode 100644
index 0000000..aae9c9c
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/explosion/boat/step3.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/explosion/boat/step4.png b/examples/animation/sub-attaq/pics/big/explosion/boat/step4.png
new file mode 100644
index 0000000..d697c1b
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/explosion/boat/step4.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/explosion/submarine/step1.png b/examples/animation/sub-attaq/pics/big/explosion/submarine/step1.png
new file mode 100644
index 0000000..88ca514
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/explosion/submarine/step1.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/explosion/submarine/step2.png b/examples/animation/sub-attaq/pics/big/explosion/submarine/step2.png
new file mode 100644
index 0000000..524f589
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/explosion/submarine/step2.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/explosion/submarine/step3.png b/examples/animation/sub-attaq/pics/big/explosion/submarine/step3.png
new file mode 100644
index 0000000..2cca1e8
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/explosion/submarine/step3.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/explosion/submarine/step4.png b/examples/animation/sub-attaq/pics/big/explosion/submarine/step4.png
new file mode 100644
index 0000000..82100a8
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/explosion/submarine/step4.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/submarine.png b/examples/animation/sub-attaq/pics/big/submarine.png
new file mode 100644
index 0000000..df435dc
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/submarine.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/surface.png b/examples/animation/sub-attaq/pics/big/surface.png
new file mode 100644
index 0000000..4eba29e
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/surface.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/big/torpedo.png b/examples/animation/sub-attaq/pics/big/torpedo.png
new file mode 100644
index 0000000..f9c2687
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/big/torpedo.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/scalable/background-n810.svg b/examples/animation/sub-attaq/pics/scalable/background-n810.svg
new file mode 100644
index 0000000..ece9f7a
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/background-n810.svg
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<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"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg2588"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="background-n810.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <metadata
+ id="metadata28">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:window-height="1141"
+ inkscape:window-width="1920"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="1.2399902"
+ inkscape:cx="375"
+ inkscape:cy="461.074"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="layer1" />
+ <defs
+ id="defs2590">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective30" />
+ <linearGradient
+ id="linearGradient3746">
+ <stop
+ id="stop3748"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3750"
+ style="stop-color:#0074b7;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <radialGradient
+ cx="82.966125"
+ cy="-178.42453"
+ r="526.79456"
+ fx="82.966125"
+ fy="-178.42453"
+ id="radialGradient3880"
+ xlink:href="#linearGradient3746"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4952094,0.2388475,-0.1040669,0.3734391,-208.61982,418.216)" />
+ <linearGradient
+ id="linearGradient3624">
+ <stop
+ id="stop3626"
+ style="stop-color:#3a8daf;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3636"
+ style="stop-color:#252525;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="552.98486"
+ y1="390.56842"
+ x2="549.39465"
+ y2="702.3479"
+ id="linearGradient3630"
+ xlink:href="#linearGradient3624"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3373776,0,0,1.186038,-986.88716,67.776416)" />
+ <linearGradient
+ id="linearGradient3816">
+ <stop
+ id="stop3818"
+ style="stop-color:#ad8b00;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3820"
+ style="stop-color:#ad8b00;stop-opacity:0"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="573"
+ y1="755.46222"
+ x2="573"
+ y2="700.13464"
+ id="linearGradient3826"
+ xlink:href="#linearGradient3816"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2561681,-151.5,-34.518664)" />
+ <linearGradient
+ id="linearGradient5097">
+ <stop
+ id="stop5099"
+ style="stop-color:#19a2db;stop-opacity:0"
+ offset="0" />
+ <stop
+ id="stop5109"
+ style="stop-color:#1379a7;stop-opacity:0.49803922"
+ offset="0.30000001" />
+ <stop
+ id="stop5101"
+ style="stop-color:#0e5173;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="590.84674"
+ y1="274.57559"
+ x2="590.84674"
+ y2="334.01376"
+ id="linearGradient5103"
+ xlink:href="#linearGradient5097"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-151.5,156.75229)"
+ spreadMethod="pad" />
+ </defs>
+ <g
+ id="layer1">
+ <rect
+ width="1053.5891"
+ height="206.64989"
+ x="-151.79456"
+ y="330.16019"
+ id="rect3638"
+ style="opacity:1;fill:url(#radialGradient3880);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.1880002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ width="1054.4708"
+ height="364.81519"
+ x="-152.23541"
+ y="533.48895"
+ id="rect3622"
+ style="opacity:1;fill:url(#linearGradient3630);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13464069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M -152.5,877.11847 C 120.5,865.81296 -202.86309,769.3663 109.5,871.29717 C 172.96247,892.00636 243.5,872.55334 297.5,871.29717 C 351.5,870.041 311.5,859.80335 358.5,876.13354 C 405.5,892.46372 553.5,861.09903 598.5,854.8182 C 643.5,848.53736 756.5,841.79698 795.5,853.10249 C 834.5,864.408 904.5,866.2725 904.5,866.2725 L 901.5,903.95754 L -154.5,902.70137 L -152.5,877.11847 z"
+ id="path3814"
+ style="fill:url(#linearGradient3826);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 902.20121,894.16261 C 632.01828,889.43035 756.73005,860.2801 614.20403,894.1311 C 596.58819,898.315 408.23621,883.21212 400.43291,894.1311 C 376.86263,927.11261 75.265447,868.1243 34.250926,886.79082 C 31.281885,888.14209 12.514878,884.22134 -12.264082,889.72008 C -48.555335,897.77353 -64.717178,885.62471 -103.31472,890.35697 C -141.91229,895.08922 -145.87102,891.93439 -145.87102,891.93439 L -152.79879,903.10131 L 892.3044,902.5755 L 902.20121,894.16261 z"
+ id="path3828"
+ style="fill:#ad8b00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/scalable/background.svg b/examples/animation/sub-attaq/pics/scalable/background.svg
new file mode 100644
index 0000000..0be2680
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/background.svg
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<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"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg2588"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="background.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <metadata
+ id="metadata28">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:window-height="1141"
+ inkscape:window-width="1920"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="0.93884027"
+ inkscape:cx="473.72605"
+ inkscape:cy="538.63678"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="layer1" />
+ <defs
+ id="defs2590">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective30" />
+ <linearGradient
+ id="linearGradient3746">
+ <stop
+ id="stop3748"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3750"
+ style="stop-color:#0074b7;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <radialGradient
+ cx="82.966125"
+ cy="-178.42453"
+ r="526.79456"
+ fx="82.966125"
+ fy="-178.42453"
+ id="radialGradient3880"
+ xlink:href="#linearGradient3746"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4952094,0.3367191,-0.1040669,0.5264617,-208.61982,282.52272)" />
+ <linearGradient
+ id="linearGradient3624">
+ <stop
+ id="stop3626"
+ style="stop-color:#3a8daf;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3636"
+ style="stop-color:#252525;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="552.98486"
+ y1="390.56842"
+ x2="549.39465"
+ y2="702.3479"
+ id="linearGradient3630"
+ xlink:href="#linearGradient3624"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3373776,0,0,1.5004634,-986.88716,-154.07447)" />
+ <linearGradient
+ id="linearGradient3816">
+ <stop
+ id="stop3818"
+ style="stop-color:#ad8b00;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3820"
+ style="stop-color:#ad8b00;stop-opacity:0"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="573"
+ y1="755.46222"
+ x2="573"
+ y2="700.13464"
+ id="linearGradient3826"
+ xlink:href="#linearGradient3816"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.6033628,-151.5,-294.0167)" />
+ <linearGradient
+ id="linearGradient5097">
+ <stop
+ id="stop5099"
+ style="stop-color:#19a2db;stop-opacity:0"
+ offset="0" />
+ <stop
+ id="stop5109"
+ style="stop-color:#1379a7;stop-opacity:0.49803922"
+ offset="0.30000001" />
+ <stop
+ id="stop5101"
+ style="stop-color:#0e5173;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="590.84674"
+ y1="274.57559"
+ x2="590.84674"
+ y2="334.01376"
+ id="linearGradient5103"
+ xlink:href="#linearGradient5097"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-151.5,156.75229)"
+ spreadMethod="pad" />
+ </defs>
+ <g
+ id="layer1">
+ <rect
+ width="1053.5891"
+ height="291.32797"
+ x="-151.79456"
+ y="158.38464"
+ id="rect3638"
+ style="opacity:1;fill:url(#radialGradient3880);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.1880002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ width="1054.4708"
+ height="461.52972"
+ x="-152.23541"
+ y="435.10107"
+ id="rect3622"
+ style="opacity:1;fill:url(#linearGradient3630);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13464069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M -152.5,869.5896 C 120.5,855.15934 -202.86309,732.0556 109.5,862.15934 C 172.96247,888.59238 243.5,863.7627 297.5,862.15934 C 351.5,860.55598 311.5,847.48872 358.5,868.33244 C 405.5,889.17615 553.5,849.14252 598.5,841.12571 C 643.5,833.1089 756.5,824.50553 795.5,838.9358 C 834.5,853.36606 904.5,855.74589 904.5,855.74589 L 901.5,903.84677 L -154.5,902.24341 L -152.5,869.5896 z"
+ id="path3814"
+ style="fill:url(#linearGradient3826);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 902.20121,891.3446 C 632.01828,885.30439 756.73005,848.09724 614.20403,891.30439 C 596.58819,896.64468 408.23621,877.36748 400.43291,891.30439 C 376.86263,933.40172 75.265447,858.10952 34.250926,881.93531 C 31.281885,883.66006 12.514878,878.65564 -12.264082,885.67419 C -48.555335,895.95355 -64.717178,880.4469 -103.31472,886.48711 C -141.91229,892.52732 -145.87102,888.50052 -145.87102,888.50052 L -152.79879,902.75389 L 892.3044,902.08275 L 902.20121,891.3446 z"
+ id="path3828"
+ style="fill:#ad8b00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/scalable/boat.svg b/examples/animation/sub-attaq/pics/scalable/boat.svg
new file mode 100644
index 0000000..5298821b
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/boat.svg
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg2584">
+ <defs
+ id="defs2666">
+ <linearGradient
+ x1="542.5"
+ y1="222.59448"
+ x2="559"
+ y2="222.59448"
+ id="linearGradient3387"
+ xlink:href="#linearGradient3746"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-110.6791,190.19124)" />
+ <linearGradient
+ id="linearGradient3167">
+ <stop
+ id="stop3169"
+ style="stop-color:#464646;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3345"
+ style="stop-color:#848788;stop-opacity:1"
+ offset="0.44021741" />
+ <stop
+ id="stop3347"
+ style="stop-color:#9ca0a2;stop-opacity:1"
+ offset="0.56799388" />
+ <stop
+ id="stop3171"
+ style="stop-color:#b5babd;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="474.23065"
+ y1="229.92336"
+ x2="474.1944"
+ y2="218.27365"
+ id="linearGradient3416"
+ xlink:href="#linearGradient3167"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-125.98032,185.95625)" />
+ <linearGradient
+ id="linearGradient3692">
+ <stop
+ id="stop3694"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3696"
+ style="stop-color:#b6b6b6;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="573.5"
+ y1="244.2056"
+ x2="578.25"
+ y2="216.9556"
+ id="linearGradient3972"
+ xlink:href="#linearGradient3692"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-126.5541,188.56624)" />
+ <linearGradient
+ id="linearGradient3438">
+ <stop
+ id="stop3440"
+ style="stop-color:#939393;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3444"
+ style="stop-color:#d6d6d6;stop-opacity:1"
+ offset="0.12354442" />
+ <stop
+ id="stop3446"
+ style="stop-color:#dadada;stop-opacity:1"
+ offset="0.74055624" />
+ <stop
+ id="stop3442"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="660.29303"
+ y1="256.53284"
+ x2="444.79303"
+ y2="255.62085"
+ id="linearGradient3948"
+ xlink:href="#linearGradient3438"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-126.5541,185.56624)" />
+ <linearGradient
+ x1="542.5"
+ y1="222.59448"
+ x2="559"
+ y2="222.59448"
+ id="linearGradient3990"
+ xlink:href="#linearGradient3746"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-132.8041,190.19124)" />
+ <linearGradient
+ id="linearGradient3746">
+ <stop
+ id="stop3748"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3750"
+ style="stop-color:#0074b7;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="542.5"
+ y1="222.59448"
+ x2="559"
+ y2="222.59448"
+ id="linearGradient3994"
+ xlink:href="#linearGradient3746"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-88.054101,190.19124)" />
+ <linearGradient
+ id="linearGradient3428">
+ <stop
+ id="stop3430"
+ style="stop-color:#464646;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3432"
+ style="stop-color:#848788;stop-opacity:1"
+ offset="0.18306103" />
+ <stop
+ id="stop3434"
+ style="stop-color:#9ca0a2;stop-opacity:1"
+ offset="0.66368055" />
+ <stop
+ id="stop3436"
+ style="stop-color:#b5babd;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="592.92798"
+ y1="199.43727"
+ x2="557.05743"
+ y2="196.5448"
+ id="linearGradient3426"
+ xlink:href="#linearGradient3428"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-102.5217,149.09845)" />
+ </defs>
+ <g
+ id="layer1">
+ <g
+ id="boat">
+ <path
+ d="M 296.669,434.15623 C 376.12538,436.50959 448.282,436.46711 542.42304,434.15623 C 542.42304,434.15623 544.22253,425.03531 542.42304,422.57953 C 432.90655,403.86953 296.669,418.12547 296.669,422.57953 L 296.669,434.15623 z"
+ id="path3469"
+ style="fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3.4975698;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" />
+ <rect
+ width="3.4280596"
+ height="29.611124"
+ x="647.59613"
+ y="173.91156"
+ transform="matrix(0.9327494,0.3605254,-0.3633626,0.9316478,0,0)"
+ id="rect3408"
+ style="opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ width="48.499989"
+ height="8.5"
+ x="318.48221"
+ y="405.82172"
+ transform="matrix(0.9999952,3.0887777e-3,-3.0887777e-3,0.9999952,0,0)"
+ id="rect3376"
+ style="opacity:1;fill:url(#linearGradient3416);fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 382.4459,430.66072 C 382.4459,430.66072 420.85999,388.74829 397.4459,385.66072 L 488.4459,397.66072 L 488.4459,432.66072 L 382.4459,430.66072 z"
+ id="path3952"
+ style="fill:url(#linearGradient3972);fill-opacity:1;fill-rule:evenodd;stroke:#323232;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 301.4459,429.66072 C 301.4459,429.66072 330.46329,468.66072 343.4459,468.66072 C 355.42851,471.91072 507.57644,473.70653 525.4459,465.91072 C 534.58031,461.59104 537.90602,455.58662 539.4459,429.66072 C 473.70193,439.43306 371.2651,439.78219 301.4459,429.66072 z"
+ id="path3938"
+ style="fill:url(#linearGradient3948);fill-opacity:1;fill-rule:evenodd;stroke:#545454;stroke-width:3.0999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 339.44863,416.12222 L 357.69854,416.17859 L 368.1622,427.96097 L 339.41234,427.87217 L 339.44863,416.12222 z"
+ id="rect3378"
+ style="fill:#dedede;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" />
+ <rect
+ width="13.5"
+ height="17"
+ x="411.19589"
+ y="404.28574"
+ id="rect3974"
+ style="opacity:1;fill:url(#linearGradient3990);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ width="13.5"
+ height="17"
+ x="455.94589"
+ y="404.28574"
+ id="rect3992"
+ style="opacity:1;fill:url(#linearGradient3994);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 295.6959,421.91072 C 360.77923,430.41072 446.61257,432.91072 541.9459,421.91072 C 541.9459,421.91072 543.74902,428.6076 541.9459,430.41072 C 432.20839,444.14823 295.6959,433.68104 295.6959,430.41072 L 295.6959,421.91072 z"
+ id="rect2558"
+ style="fill:#dedede;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" />
+ <rect
+ width="94.427879"
+ height="7.236649"
+ x="437.10614"
+ y="342.2645"
+ transform="matrix(0.9947793,0.1020501,-0.1079723,0.9941539,0,0)"
+ id="rect2569"
+ style="opacity:1;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:#404040;stroke-width:3.0365274;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ width="13.5"
+ height="17"
+ x="433.32089"
+ y="404.28574"
+ id="rect3385"
+ style="opacity:1;fill:url(#linearGradient3387);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 402.86916,380.21847 L 489.80407,388.85485 L 491.52271,394.54919 L 397.58781,384.91281 L 402.86916,380.21847 z"
+ id="rect3466"
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#404040;stroke-width:3.03650045;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" />
+ <rect
+ width="34.5"
+ height="14.5"
+ x="456.4783"
+ y="336.94293"
+ transform="matrix(0.997157,7.5351915e-2,-7.5351915e-2,0.997157,0,0)"
+ id="rect3418"
+ style="opacity:1;fill:url(#linearGradient3426);fill-opacity:1;fill-rule:nonzero;stroke:#494949;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ transform="matrix(0.9246214,0.3808874,-0.3808874,0.9246214,-13.252851,-40.129692)"
+ id="flag">
+ <rect
+ width="19.75"
+ height="27.75"
+ x="193.34448"
+ y="-709"
+ transform="matrix(0,1,-1,0,0,0)"
+ id="rect3389"
+ style="opacity:1;fill:#b20000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ width="27.25"
+ height="5.75"
+ x="681.5"
+ y="200.59448"
+ id="rect3393"
+ style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ width="5.75"
+ height="19.5"
+ x="691.25"
+ y="193.59448"
+ id="rect3395"
+ style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ width="27.75"
+ height="2.5"
+ x="681.5"
+ y="202.34448"
+ id="rect3397"
+ style="opacity:1;fill:#000080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ width="3"
+ height="19.25"
+ x="692.5"
+ y="193.59448"
+ id="rect3399"
+ style="opacity:1;fill:#000080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/scalable/bomb.svg b/examples/animation/sub-attaq/pics/scalable/bomb.svg
new file mode 100644
index 0000000..294771a
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/bomb.svg
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg3121">
+ <defs
+ id="defs3123">
+ <radialGradient
+ cx="-135.625"
+ cy="148.71948"
+ r="7.625"
+ fx="-135.625"
+ fy="148.71948"
+ id="radialGradient3439"
+ xlink:href="#linearGradient3366"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ x1="-132.85063"
+ y1="173.6969"
+ x2="-145.3662"
+ y2="177.59828"
+ id="linearGradient3418"
+ xlink:href="#linearGradient3366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.2134297,-0.5943658,0.6658882,-0.2391126,-274.53441,123.00067)" />
+ <linearGradient
+ x1="-141.85466"
+ y1="181.49153"
+ x2="-144.95044"
+ y2="175.90179"
+ id="linearGradient3414"
+ xlink:href="#linearGradient3366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2134297,-0.5943658,-0.6658882,-0.2391126,-15.893355,122.67824)" />
+ <linearGradient
+ x1="-149.5"
+ y1="177.59448"
+ x2="-145.7928"
+ y2="180.05936"
+ id="linearGradient3410"
+ xlink:href="#linearGradient3366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6315243,0,0,0.7075182,-227.03781,54.321514)" />
+ <linearGradient
+ x1="-140.46242"
+ y1="177.40488"
+ x2="-147.04802"
+ y2="172.66473"
+ id="linearGradient3406"
+ xlink:href="#linearGradient3366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6315243,0,0,-0.7075182,-226.40365,274.91611)" />
+ <linearGradient
+ x1="-147.2406"
+ y1="180.95567"
+ x2="-140.01878"
+ y2="175.57777"
+ id="linearGradient3402"
+ xlink:href="#linearGradient3366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6315243,0,0,-0.7075182,-64.045217,275.07466)" />
+ <linearGradient
+ x1="-146.98956"
+ y1="174.00922"
+ x2="-142.60332"
+ y2="179.38712"
+ id="linearGradient3398"
+ xlink:href="#linearGradient3366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6315243,0,0,0.7075182,-62.683611,54.187362)" />
+ <linearGradient
+ id="linearGradient3366">
+ <stop
+ id="stop3368"
+ style="stop-color:#bcbcbc;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3370"
+ style="stop-color:#191b1c;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <radialGradient
+ cx="-208.95004"
+ cy="173.10576"
+ r="31.667252"
+ fx="-208.95004"
+ fy="173.10576"
+ id="radialGradient3364"
+ xlink:href="#linearGradient3366"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <g
+ id="layer1">
+ <g
+ transform="translate(419.4996,488.13454)"
+ id="mine">
+ <path
+ d="M -167.5843,186.54079 A 31.466251,31.466251 0 1 1 -230.5168,186.54079 A 31.466251,31.466251 0 1 1 -167.5843,186.54079 z"
+ transform="matrix(0.6341613,0,0,0.6341613,-18.521242,45.718192)"
+ id="path2586"
+ style="opacity:1;fill:url(#radialGradient3364);fill-opacity:1;stroke:#131313;stroke-width:3.54799318;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M -155.20193,175.4167 C -157.60085,176.6451 -156.78074,184.26068 -156.78074,184.26068 C -156.78074,184.26068 -148.33787,181.58301 -148.57092,178.60053 C -148.74283,176.40051 -153.23774,174.41092 -155.20193,175.4167 z"
+ id="path3382"
+ style="fill:url(#linearGradient3398);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M -156.56354,153.84532 C -158.96246,152.61693 -158.14235,145.00135 -158.14235,145.00135 C -158.14235,145.00135 -149.69948,147.67902 -149.93253,150.66149 C -150.10444,152.86151 -154.59935,154.85111 -156.56354,153.84532 z"
+ id="path3400"
+ style="fill:url(#linearGradient3402);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M -133.88532,153.68678 C -131.48641,152.45838 -132.30652,144.8428 -132.30652,144.8428 C -132.30652,144.8428 -140.74938,147.52047 -140.51633,150.50295 C -140.34442,152.70297 -135.84951,154.69256 -133.88532,153.68678 z"
+ id="path3404"
+ style="fill:url(#linearGradient3406);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M -134.51948,175.55085 C -132.12057,176.77925 -132.94068,184.39483 -132.94068,184.39483 C -132.94068,184.39483 -141.38355,181.71716 -141.15049,178.73469 C -140.97858,176.53467 -136.48367,174.54507 -134.51948,175.55085 z"
+ id="path3408"
+ style="fill:url(#linearGradient3410);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M -161.25709,168.78221 C -163.22395,170.62484 -170.11427,165.85236 -170.11427,165.85236 C -170.11427,165.85236 -164.7408,160.23808 -162.01257,161.46538 C -160.00011,162.37068 -159.64667,167.27352 -161.25709,168.78221 z"
+ id="path3412"
+ style="fill:url(#linearGradient3414);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M -129.17068,169.10464 C -127.20382,170.94727 -120.3135,166.17478 -120.3135,166.17478 C -120.3135,166.17478 -125.68697,160.5605 -128.41519,161.7878 C -130.42766,162.69311 -130.7811,167.59595 -129.17068,169.10464 z"
+ id="path3416"
+ style="fill:url(#linearGradient3418);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M -126,151.21948 A 6.625,6.625 0 1 1 -139.25,151.21948 A 6.625,6.625 0 1 1 -126,151.21948 z"
+ transform="matrix(0.6341613,0,0,0.6341613,-61.039517,68.324922)"
+ id="path3426"
+ style="opacity:1;fill:url(#radialGradient3439);fill-opacity:1;stroke:#131313;stroke-width:3.54799318;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/scalable/sand.svg b/examples/animation/sub-attaq/pics/scalable/sand.svg
new file mode 100644
index 0000000..8af11b7
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/sand.svg
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg2596">
+ <defs
+ id="defs2598">
+ <linearGradient
+ id="linearGradient3708">
+ <stop
+ id="stop3710"
+ style="stop-color:#202020;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3712"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="518.26996"
+ y1="497.31476"
+ x2="533.02924"
+ y2="497.31476"
+ id="linearGradient3794"
+ xlink:href="#linearGradient3708"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3718">
+ <stop
+ id="stop3720"
+ style="stop-color:#bcbcbc;stop-opacity:0.28169015"
+ offset="0" />
+ <stop
+ id="stop3722"
+ style="stop-color:#bcbcbc;stop-opacity:0"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="516.89508"
+ y1="503.50137"
+ x2="516.89508"
+ y2="543.80646"
+ id="linearGradient3792"
+ xlink:href="#linearGradient3718"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9947644,0,0,1.3346457,2.7877039,-166.60153)" />
+ <linearGradient
+ id="linearGradient3692">
+ <stop
+ id="stop3694"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3696"
+ style="stop-color:#b6b6b6;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="506.95975"
+ y1="469.73706"
+ x2="525.41608"
+ y2="469.73706"
+ id="linearGradient3790"
+ xlink:href="#linearGradient3692"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3816">
+ <stop
+ id="stop3818"
+ style="stop-color:#ad8b00;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3820"
+ style="stop-color:#ad8b00;stop-opacity:0"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="573"
+ y1="755.46222"
+ x2="573"
+ y2="700.13464"
+ id="linearGradient3826"
+ xlink:href="#linearGradient3816"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.6033628,-150.63569,-350.3846)" />
+ </defs>
+ <g
+ id="layer1">
+ <path
+ d="M -151.63569,813.2217 C 121.3643,798.79144 -201.99878,675.6877 110.3643,805.79144 C 173.82677,832.22448 244.3643,807.3948 298.3643,805.79144 C 352.3643,804.18808 312.3643,791.12082 359.3643,811.96454 C 406.3643,832.80825 554.3643,792.77462 599.3643,784.75781 C 644.3643,776.741 757.36426,768.13763 796.36426,782.5679 C 835.36426,796.99816 905.36426,799.37799 905.36426,799.37799 L 902.36426,847.47887 L -153.63569,845.87551 L -151.63569,813.2217 z"
+ id="path3814"
+ style="fill:url(#linearGradient3826);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 908.86426,836.95812 C 635.8643,830.91791 761.87636,793.71076 617.8643,836.91791 C 600.0648,842.2582 409.74894,822.981 401.8643,836.91791 C 378.04825,879.01524 73.306465,803.72304 31.864305,827.54883 C 28.864305,829.27358 9.9016246,824.26916 -15.135695,831.28771 C -51.805335,841.56707 -68.135695,826.06042 -107.1357,832.10063 C -146.1357,838.14084 -150.13569,834.11404 -150.13569,834.11404 L -157.13569,848.36741 L 898.86426,847.69627 L 908.86426,836.95812 z"
+ id="path3828"
+ style="fill:#ad8b00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/scalable/see.svg b/examples/animation/sub-attaq/pics/scalable/see.svg
new file mode 100644
index 0000000..0666691
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/see.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg2650">
+ <defs
+ id="defs2652">
+ <linearGradient
+ id="linearGradient3624">
+ <stop
+ id="stop3626"
+ style="stop-color:#3a8daf;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3636"
+ style="stop-color:#252525;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="552.98486"
+ y1="390.56842"
+ x2="549.39465"
+ y2="702.3479"
+ id="linearGradient3630"
+ xlink:href="#linearGradient3624"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3373776,0,0,1.5004634,-996.17287,-279.00679)" />
+ </defs>
+ <g
+ id="layer1">
+ <rect
+ width="1054.4708"
+ height="461.52972"
+ x="-161.52115"
+ y="310.16876"
+ id="rect3622"
+ style="opacity:1;fill:url(#linearGradient3630);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13464069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/scalable/sky.svg b/examples/animation/sub-attaq/pics/scalable/sky.svg
new file mode 100644
index 0000000..1546c08
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/sky.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg2721">
+ <defs
+ id="defs2723">
+ <linearGradient
+ id="linearGradient3746">
+ <stop
+ id="stop3748"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3750"
+ style="stop-color:#0074b7;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <radialGradient
+ cx="82.966125"
+ cy="-178.42453"
+ r="526.79456"
+ fx="82.966125"
+ fy="-178.42453"
+ id="radialGradient3880"
+ xlink:href="#linearGradient3746"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.4952094,0.3367191,-0.1040669,0.5264617,-235.04839,425.12197)" />
+ </defs>
+ <g
+ id="layer1">
+ <rect
+ width="1053.5891"
+ height="291.32797"
+ x="-178.22313"
+ y="300.98392"
+ id="rect3638"
+ style="opacity:1;fill:url(#radialGradient3880);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.1880002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/scalable/sub-attaq.svg b/examples/animation/sub-attaq/pics/scalable/sub-attaq.svg
new file mode 100644
index 0000000..b075179
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/sub-attaq.svg
@@ -0,0 +1,1473 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<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="1052.3622"
+ height="744.09448"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="sub-attaq.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs4">
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3366"
+ id="radialGradient3439"
+ cx="-135.625"
+ cy="148.71948"
+ fx="-135.625"
+ fy="148.71948"
+ r="7.625"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3366"
+ id="linearGradient3418"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.2134297,-0.5943658,0.6658882,-0.2391126,-274.53441,123.00067)"
+ x1="-132.85063"
+ y1="173.6969"
+ x2="-145.3662"
+ y2="177.59828" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3366"
+ id="linearGradient3414"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.2134297,-0.5943658,-0.6658882,-0.2391126,-15.893355,122.67824)"
+ x1="-141.85466"
+ y1="181.49153"
+ x2="-144.95044"
+ y2="175.90179" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3366"
+ id="linearGradient3410"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6315243,0,0,0.7075182,-227.03781,54.321514)"
+ x1="-149.5"
+ y1="177.59448"
+ x2="-145.7928"
+ y2="180.05936" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3366"
+ id="linearGradient3406"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6315243,0,0,-0.7075182,-226.40365,274.91611)"
+ x1="-140.46242"
+ y1="177.40488"
+ x2="-147.04802"
+ y2="172.66473" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3366"
+ id="linearGradient3402"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6315243,0,0,-0.7075182,-64.045217,275.07466)"
+ x1="-147.2406"
+ y1="180.95567"
+ x2="-140.01878"
+ y2="175.57777" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3366"
+ id="linearGradient3398"
+ x1="-146.98956"
+ y1="174.00922"
+ x2="-142.60332"
+ y2="179.38712"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6315243,0,0,0.7075182,-62.683611,54.187362)" />
+ <linearGradient
+ id="linearGradient3366">
+ <stop
+ id="stop3368"
+ offset="0"
+ style="stop-color:#bcbcbc;stop-opacity:1;" />
+ <stop
+ id="stop3370"
+ offset="1"
+ style="stop-color:#191b1c;stop-opacity:1;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3366"
+ id="radialGradient3364"
+ cx="-208.95004"
+ cy="173.10576"
+ fx="-208.95004"
+ fy="173.10576"
+ r="31.667252"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient5097">
+ <stop
+ style="stop-color:#19a2db;stop-opacity:0;"
+ offset="0"
+ id="stop5099" />
+ <stop
+ id="stop5109"
+ offset="0.30000001"
+ style="stop-color:#1379a7;stop-opacity:0.49803922;" />
+ <stop
+ style="stop-color:#0e5173;stop-opacity:1;"
+ offset="1"
+ id="stop5101" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3523"
+ inkscape:collect="always">
+ <stop
+ id="stop3525"
+ offset="0"
+ style="stop-color:#b9b9b9;stop-opacity:1" />
+ <stop
+ id="stop3527"
+ offset="1"
+ style="stop-color:#444444;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3438">
+ <stop
+ style="stop-color:#939393;stop-opacity:1;"
+ offset="0"
+ id="stop3440" />
+ <stop
+ id="stop3444"
+ offset="0.12354442"
+ style="stop-color:#d6d6d6;stop-opacity:1;" />
+ <stop
+ style="stop-color:#dadada;stop-opacity:1;"
+ offset="0.74055624"
+ id="stop3446" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop3442" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3428">
+ <stop
+ id="stop3430"
+ offset="0"
+ style="stop-color:#464646;stop-opacity:1;" />
+ <stop
+ style="stop-color:#848788;stop-opacity:1;"
+ offset="0.18306103"
+ id="stop3432" />
+ <stop
+ id="stop3434"
+ offset="0.66368055"
+ style="stop-color:#9ca0a2;stop-opacity:1;" />
+ <stop
+ id="stop3436"
+ offset="1"
+ style="stop-color:#b5babd;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4034">
+ <stop
+ id="stop4036"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.49803922;"
+ offset="0.5"
+ id="stop4038" />
+ <stop
+ id="stop4040"
+ offset="0.63705367"
+ style="stop-color:#ffffff;stop-opacity:0.24705882;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.12156863;"
+ offset="0.79425853"
+ id="stop4042" />
+ <stop
+ id="stop4044"
+ offset="1"
+ style="stop-color:#a0a0a0;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient4016">
+ <stop
+ style="stop-color:#283e6a;stop-opacity:1;"
+ offset="0"
+ id="stop4018" />
+ <stop
+ style="stop-color:#283e6a;stop-opacity:0;"
+ offset="1"
+ id="stop4020" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4004">
+ <stop
+ style="stop-color:#dbdbdb;stop-opacity:1;"
+ offset="0"
+ id="stop4010" />
+ <stop
+ style="stop-color:#c4c9cb;stop-opacity:1;"
+ offset="1"
+ id="stop4012" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3998">
+ <stop
+ id="stop4000"
+ offset="0"
+ style="stop-color:#adadad;stop-opacity:1;" />
+ <stop
+ id="stop4002"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3864">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3866" />
+ <stop
+ id="stop4028"
+ offset="0.5"
+ style="stop-color:#ffffff;stop-opacity:0.49803922;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.24705882;"
+ offset="0.75"
+ id="stop4030" />
+ <stop
+ id="stop4032"
+ offset="0.875"
+ style="stop-color:#ffffff;stop-opacity:0.12156863;" />
+ <stop
+ style="stop-color:#a0a0a0;stop-opacity:1;"
+ offset="1"
+ id="stop3868" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3816">
+ <stop
+ style="stop-color:#ad8b00;stop-opacity:1;"
+ offset="0"
+ id="stop3818" />
+ <stop
+ style="stop-color:#ad8b00;stop-opacity:0;"
+ offset="1"
+ id="stop3820" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3746">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3748" />
+ <stop
+ style="stop-color:#0074b7;stop-opacity:1;"
+ offset="1"
+ id="stop3750" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3718">
+ <stop
+ style="stop-color:#bcbcbc;stop-opacity:0.28169015;"
+ offset="0"
+ id="stop3720" />
+ <stop
+ style="stop-color:#bcbcbc;stop-opacity:0;"
+ offset="1"
+ id="stop3722" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3708">
+ <stop
+ style="stop-color:#202020;stop-opacity:1;"
+ offset="0"
+ id="stop3710" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop3712" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3692">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3694" />
+ <stop
+ style="stop-color:#b6b6b6;stop-opacity:1;"
+ offset="1"
+ id="stop3696" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3656">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3658" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop3660" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3624">
+ <stop
+ style="stop-color:#3a8daf;stop-opacity:1;"
+ offset="0"
+ id="stop3626" />
+ <stop
+ id="stop3636"
+ offset="1"
+ style="stop-color:#252525;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3532">
+ <stop
+ id="stop3534"
+ offset="0"
+ style="stop-color:#545454;stop-opacity:1;" />
+ <stop
+ style="stop-color:#848788;stop-opacity:1;"
+ offset="0.44021741"
+ id="stop3536" />
+ <stop
+ id="stop3538"
+ offset="0.56799388"
+ style="stop-color:#9ca0a2;stop-opacity:1;" />
+ <stop
+ id="stop3540"
+ offset="1"
+ style="stop-color:#565d60;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3345">
+ <stop
+ id="stop3348"
+ offset="0"
+ style="stop-color:#898989;stop-opacity:1;" />
+ <stop
+ style="stop-color:#9ea1a2;stop-opacity:1;"
+ offset="0.44021741"
+ id="stop3350" />
+ <stop
+ id="stop3352"
+ offset="0.56799388"
+ style="stop-color:#bbbdbf;stop-opacity:1;" />
+ <stop
+ id="stop3354"
+ offset="1"
+ style="stop-color:#f0f1f2;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3227">
+ <stop
+ style="stop-color:#444444;stop-opacity:1;"
+ offset="0"
+ id="stop3229" />
+ <stop
+ style="stop-color:#b0b0b0;stop-opacity:1;"
+ offset="1"
+ id="stop3232" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3435">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop3437" />
+ <stop
+ style="stop-color:#c0c0c0;stop-opacity:0;"
+ offset="1"
+ id="stop3439" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3421">
+ <stop
+ style="stop-color:#444444;stop-opacity:1;"
+ offset="0"
+ id="stop3423" />
+ <stop
+ style="stop-color:#444444;stop-opacity:0;"
+ offset="1"
+ id="stop3425" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3293">
+ <stop
+ style="stop-color:#c4b434;stop-opacity:1;"
+ offset="0"
+ id="stop3295" />
+ <stop
+ style="stop-color:#9b5500;stop-opacity:1;"
+ offset="1"
+ id="stop3297" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3229">
+ <stop
+ style="stop-color:#125a7a;stop-opacity:1;"
+ offset="0"
+ id="stop3231" />
+ <stop
+ style="stop-color:#308fc0;stop-opacity:1;"
+ offset="1"
+ id="stop3233" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3219">
+ <stop
+ id="stop3221"
+ offset="0"
+ style="stop-color:#a55b00;stop-opacity:1;" />
+ <stop
+ id="stop3223"
+ offset="1"
+ style="stop-color:#f4e45e;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3189">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3191" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3193" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3167">
+ <stop
+ style="stop-color:#464646;stop-opacity:1;"
+ offset="0"
+ id="stop3169" />
+ <stop
+ id="stop3345"
+ offset="0.44021741"
+ style="stop-color:#848788;stop-opacity:1;" />
+ <stop
+ style="stop-color:#9ca0a2;stop-opacity:1;"
+ offset="0.56799388"
+ id="stop3347" />
+ <stop
+ style="stop-color:#b5babd;stop-opacity:1;"
+ offset="1"
+ id="stop3171" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3167"
+ id="linearGradient3175"
+ x1="443.95602"
+ y1="315.31854"
+ x2="443.95602"
+ y2="247.85609"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4908502,0,0,0.4579593,350.98557,542.12189)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3219"
+ id="linearGradient3253"
+ gradientUnits="userSpaceOnUse"
+ x1="325.57214"
+ y1="280.13632"
+ x2="312.84424"
+ y2="257.60013" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3229"
+ id="linearGradient3255"
+ gradientUnits="userSpaceOnUse"
+ x1="310.01578"
+ y1="255.47881"
+ x2="325.92572"
+ y2="280.13632" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3219"
+ id="linearGradient3321"
+ gradientUnits="userSpaceOnUse"
+ x1="325.57214"
+ y1="280.13632"
+ x2="312.84424"
+ y2="257.60013" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3229"
+ id="linearGradient3323"
+ gradientUnits="userSpaceOnUse"
+ x1="310.01578"
+ y1="255.47881"
+ x2="325.92572"
+ y2="280.13632" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3219"
+ id="linearGradient3331"
+ gradientUnits="userSpaceOnUse"
+ x1="325.57214"
+ y1="280.13632"
+ x2="312.84424"
+ y2="257.60013" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3229"
+ id="linearGradient3333"
+ gradientUnits="userSpaceOnUse"
+ x1="310.01578"
+ y1="255.47881"
+ x2="325.92572"
+ y2="280.13632" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3293"
+ id="linearGradient3343"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.3292883,0,0,1.10796,1.5038593,-24.232315)"
+ x1="359.5589"
+ y1="258.84247"
+ x2="370.88239"
+ y2="258.84247" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3219"
+ id="linearGradient3365"
+ gradientUnits="userSpaceOnUse"
+ x1="325.57214"
+ y1="280.13632"
+ x2="312.84424"
+ y2="257.60013" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3229"
+ id="linearGradient3367"
+ gradientUnits="userSpaceOnUse"
+ x1="310.01578"
+ y1="255.47881"
+ x2="325.92572"
+ y2="280.13632" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3219"
+ id="linearGradient3369"
+ gradientUnits="userSpaceOnUse"
+ x1="325.57214"
+ y1="280.13632"
+ x2="312.84424"
+ y2="257.60013" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3229"
+ id="linearGradient3371"
+ gradientUnits="userSpaceOnUse"
+ x1="310.01578"
+ y1="255.47881"
+ x2="325.92572"
+ y2="280.13632" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3219"
+ id="linearGradient3379"
+ gradientUnits="userSpaceOnUse"
+ x1="325.57214"
+ y1="280.13632"
+ x2="312.84424"
+ y2="257.60013" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3229"
+ id="linearGradient3381"
+ gradientUnits="userSpaceOnUse"
+ x1="310.01578"
+ y1="255.47881"
+ x2="325.92572"
+ y2="280.13632" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3293"
+ id="linearGradient3385"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.3267302,0,0,1.1332782,-1.5786343,-29.194748)"
+ x1="371.79858"
+ y1="258.84247"
+ x2="364.49646"
+ y2="258.84247" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3293"
+ id="linearGradient3401"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.9807835,0,0,1.1280701,-361.45126,-28.553769)"
+ x1="371.79858"
+ y1="258.84247"
+ x2="364.49646"
+ y2="258.84247" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3421"
+ id="radialGradient3431"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1862613,0,0,0.3638703,-186.86143,179.02055)"
+ cx="432.3343"
+ cy="233.80295"
+ fx="432.3343"
+ fy="233.80295"
+ r="59.056834" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3435"
+ id="radialGradient3441"
+ cx="290.5"
+ cy="244.34448"
+ fx="290.5"
+ fy="244.34448"
+ r="37.5"
+ gradientTransform="matrix(0.8202102,0.8202102,-0.7960458,0.7960458,246.73838,-189.686)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3345"
+ id="linearGradient3311"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.466978,0,0,0.4500435,352.00841,540.25044)"
+ x1="510.99884"
+ y1="161.99408"
+ x2="396.48914"
+ y2="161.99408" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3421"
+ id="radialGradient3339"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4181493,0,0,0.1282619,386.09461,620.15777)"
+ cx="432.3343"
+ cy="233.80295"
+ fx="432.3343"
+ fy="233.80295"
+ r="59.056834" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3219"
+ id="linearGradient3434"
+ gradientUnits="userSpaceOnUse"
+ x1="325.57214"
+ y1="280.13632"
+ x2="312.84424"
+ y2="257.60013" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3229"
+ id="linearGradient3436"
+ gradientUnits="userSpaceOnUse"
+ x1="310.01578"
+ y1="255.47881"
+ x2="325.92572"
+ y2="280.13632" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3532"
+ id="linearGradient3520"
+ x1="525"
+ y1="371.09448"
+ x2="525"
+ y2="395.09448"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5865192,0,0,0.2518015,339.73218,572.99479)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3624"
+ id="linearGradient3630"
+ x1="552.98486"
+ y1="390.56842"
+ x2="549.39465"
+ y2="702.3479"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3373776,0,0,1.5004634,-835.38716,-310.82676)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3656"
+ id="radialGradient3662"
+ cx="656.19507"
+ cy="534.45917"
+ fx="656.19507"
+ fy="534.45917"
+ r="13.227922"
+ gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3656"
+ id="radialGradient3668"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)"
+ cx="656.19507"
+ cy="534.45917"
+ fx="656.19507"
+ fy="534.45917"
+ r="13.227922" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3656"
+ id="radialGradient3672"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)"
+ cx="656.19507"
+ cy="534.45917"
+ fx="656.19507"
+ fy="534.45917"
+ r="13.227922" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3656"
+ id="radialGradient3676"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)"
+ cx="656.19507"
+ cy="534.45917"
+ fx="656.19507"
+ fy="534.45917"
+ r="13.227922" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3692"
+ id="linearGradient3772"
+ gradientUnits="userSpaceOnUse"
+ x1="506.95975"
+ y1="469.73706"
+ x2="525.41608"
+ y2="469.73706" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3718"
+ id="linearGradient3774"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9947644,0,0,1.3346457,2.7877039,-166.60153)"
+ x1="516.89508"
+ y1="503.50137"
+ x2="516.89508"
+ y2="543.80646" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3708"
+ id="linearGradient3776"
+ gradientUnits="userSpaceOnUse"
+ x1="518.26993"
+ y1="497.31477"
+ x2="533.02923"
+ y2="497.31477" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3692"
+ id="linearGradient3790"
+ gradientUnits="userSpaceOnUse"
+ x1="506.95975"
+ y1="469.73706"
+ x2="525.41608"
+ y2="469.73706" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3718"
+ id="linearGradient3792"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9947644,0,0,1.3346457,2.7877039,-166.60153)"
+ x1="516.89508"
+ y1="503.50137"
+ x2="516.89508"
+ y2="543.80646" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3708"
+ id="linearGradient3794"
+ gradientUnits="userSpaceOnUse"
+ x1="518.26993"
+ y1="497.31477"
+ x2="533.02923"
+ y2="497.31477" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3656"
+ id="radialGradient3804"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)"
+ cx="656.19507"
+ cy="534.45917"
+ fx="656.19507"
+ fy="534.45917"
+ r="13.227922" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3656"
+ id="radialGradient3808"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.2672781,0,-144.63884)"
+ cx="656.19507"
+ cy="534.45917"
+ fx="656.19507"
+ fy="534.45917"
+ r="13.227922" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3227"
+ id="linearGradient3812"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1223608,0,0,0.3849769,-17.516054,565.40983)"
+ x1="543.5"
+ y1="205.19257"
+ x2="587.52001"
+ y2="205.19257" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3816"
+ id="linearGradient3826"
+ x1="573"
+ y1="755.46222"
+ x2="573"
+ y2="700.13464"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.6033628,0,-450.76899)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3864"
+ id="radialGradient3874"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.9674693,0.8647541,-0.8726553,1.0212484,-15.308759,-74.232772)"
+ cx="94.273849"
+ cy="89.893486"
+ fx="94.273849"
+ fy="89.893486"
+ r="74.397521" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3746"
+ id="radialGradient3880"
+ cx="82.966125"
+ cy="-178.42453"
+ fx="82.966125"
+ fy="-178.42453"
+ r="526.79456"
+ gradientTransform="matrix(1.4952094,0.3367191,-0.1040669,0.5264617,-57.119818,125.77043)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3438"
+ id="linearGradient3948"
+ x1="660.29303"
+ y1="256.53284"
+ x2="444.79303"
+ y2="255.62085"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,32.526912)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3692"
+ id="linearGradient3972"
+ x1="573.5"
+ y1="244.2056"
+ x2="578.25"
+ y2="216.9556"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,35.526912)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3746"
+ id="linearGradient3990"
+ x1="542.5"
+ y1="222.59448"
+ x2="559"
+ y2="222.59448"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-6.25,37.151912)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3746"
+ id="linearGradient3994"
+ gradientUnits="userSpaceOnUse"
+ x1="542.5"
+ y1="222.59448"
+ x2="559"
+ y2="222.59448"
+ gradientTransform="translate(38.5,37.151912)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4016"
+ id="linearGradient4022"
+ x1="639"
+ y1="262.09448"
+ x2="667"
+ y2="262.09448"
+ gradientUnits="userSpaceOnUse" />
+ <inkscape:perspective
+ id="perspective2578"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3746"
+ id="linearGradient3387"
+ gradientUnits="userSpaceOnUse"
+ x1="542.5"
+ y1="222.59448"
+ x2="559"
+ y2="222.59448"
+ gradientTransform="translate(15.875,37.151912)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3167"
+ id="linearGradient3416"
+ x1="474.23065"
+ y1="229.92336"
+ x2="474.1944"
+ y2="218.27365"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0.1004684,32.526757)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3428"
+ id="linearGradient3426"
+ x1="592.92798"
+ y1="199.43727"
+ x2="557.05743"
+ y2="196.5448"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(12.140805,-13.041887)" />
+ <filter
+ inkscape:collect="always"
+ id="filter3507">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.0523171"
+ id="feGaussianBlur3509" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3523"
+ id="linearGradient3521"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,-0.7291751,0,521.83983)"
+ x1="562.55634"
+ y1="285.89896"
+ x2="562.55634"
+ y2="244.09448" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5097"
+ id="linearGradient5103"
+ x1="590.84674"
+ y1="274.57559"
+ x2="590.84674"
+ y2="334.01376"
+ gradientUnits="userSpaceOnUse"
+ spreadMethod="pad" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3864"
+ id="radialGradient5107"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.9674693,0.8647541,-0.8726553,1.0212484,-15.308759,-74.232772)"
+ cx="94.273849"
+ cy="89.893486"
+ fx="94.273849"
+ fy="89.893486"
+ r="74.397521" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.70710678"
+ inkscape:cx="532.91407"
+ inkscape:cy="457.84365"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1674"
+ inkscape:window-height="1000"
+ inkscape:window-x="2"
+ inkscape:window-y="14"
+ showguides="false" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;fill:url(#radialGradient3880);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.1880002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3638"
+ width="1053.5891"
+ height="291.32797"
+ x="-0.29455566"
+ y="1.6323624" />
+ <path
+ style="fill:url(#radialGradient3874);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3507)"
+ d="M 158.37853,75.817898 C 130.95894,49.483192 82.14552,74.615971 85.85382,95.15981 C 49.691853,94.8009 50.214842,139.36083 83.29101,132.16343 C 144.66465,163.16454 159.26268,129.80212 164.6863,136.51386 C 225.60448,157.97672 246.34362,130.65438 265.24417,127.0714 C 294.43981,137.91859 337.16986,121.78798 297.03636,102.77604 C 331.73096,64.597047 277.96882,60.229366 253.07028,70.400868 C 191.09597,33.610112 168.89234,63.292037 158.37853,75.817898 z"
+ id="path3872"
+ sodipodi:nodetypes="cccccccc"
+ transform="matrix(1.5062893,0,0,1.1720951,618.04001,132.36768)" />
+ <rect
+ style="opacity:1;fill:url(#linearGradient3630);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.13464069;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3622"
+ width="1054.4708"
+ height="461.52972"
+ x="-0.7354126"
+ y="278.34879" />
+ <path
+ style="fill:url(#linearGradient3826);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M -0.99999999,712.83731 C 272,698.40705 -51.363087,575.30331 261,705.40705 C 324.46247,731.84009 395,707.01041 449,705.40705 C 503,703.80369 463,690.73643 510,711.58015 C 557,732.42386 705,692.39023 750,684.37342 C 795,676.35661 908,667.75324 947,682.18351 C 986,696.61377 1056,698.9936 1056,698.9936 L 1053,747.09448 L -3,745.49112 L -0.99999999,712.83731 z"
+ id="path3814"
+ sodipodi:nodetypes="cssssscccc" />
+ <rect
+ style="opacity:1;fill:url(#linearGradient3520);fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:0.56879884;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3512"
+ width="10.557344"
+ height="6.0432386"
+ x="642.3761"
+ y="666.43695" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path2455"
+ id="use3258"
+ transform="matrix(0.869168,0,0,-0.869168,81.98751,1246.5374)"
+ width="1052.3622"
+ height="744.09448" />
+ <path
+ style="fill:url(#linearGradient3812);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77744257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 593.04822,651.68104 C 593.04822,651.68104 653.65569,615.49321 639.065,637.05192 C 624.47431,658.61061 624.47431,658.61061 624.47431,658.61061 L 593.04822,651.68104 z"
+ id="path2455" />
+ <path
+ style="fill:url(#linearGradient3175);fill-opacity:1;fill-rule:evenodd;stroke:#393939;stroke-width:1.90693891;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 485.26939,643.71814 C 443.15507,651.66437 458.5319,680.53556 502.21486,686.27814 C 551.68229,692.78115 568.45042,691.0115 605.34827,686.27814 C 657.60843,679.57406 657.68143,651.78445 605.34827,643.25553 C 553.98131,634.88408 516.10913,637.89923 485.26939,643.71814 z"
+ id="path2385"
+ sodipodi:nodetypes="cssss" />
+ <path
+ style="fill:url(#radialGradient3339);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 542.18031,648.1112 C 548.56327,665.42741 608.42397,656.72745 586.93551,642.57104 C 586.93551,642.57104 543.33293,648.61096 542.18031,648.1112 z"
+ id="path3403"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:url(#linearGradient3311);fill-opacity:1;fill-rule:evenodd;stroke:#2d2d2d;stroke-width:2.07042313;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 537.39402,641.90906 C 537.39402,656.7605 583.62247,656.30589 583.62247,641.45445 L 583.62247,636.06071 C 583.62247,621.21003 537.39402,613.87461 537.39402,628.72529 L 537.39402,641.90906 z"
+ id="path3291"
+ sodipodi:nodetypes="cssss" />
+ <g
+ id="g3235"
+ transform="matrix(1.4016868,0,0,1.1319742,112.22001,-99.678822)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:url(#radialGradient3441);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.227;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path3433"
+ sodipodi:cx="303.5"
+ sodipodi:cy="263.09448"
+ sodipodi:rx="37.5"
+ sodipodi:ry="40"
+ d="M 341,263.09448 A 37.5,40 0 1 1 266,263.09448 A 37.5,40 0 1 1 341,263.09448 z"
+ transform="matrix(0.692163,0,1.4106583e-2,0.289185,275.31394,582.37251)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:#444444;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.06500006;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path3458"
+ sodipodi:cx="369.5"
+ sodipodi:cy="316.09448"
+ sodipodi:rx="27.5"
+ sodipodi:ry="7"
+ d="M 397,316.09448 A 27.5,7 0 1 1 342,316.09448 A 27.5,7 0 1 1 397,316.09448 z"
+ transform="matrix(0.5642633,0,0,0.5642633,348.03095,450.47113)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:#444444;fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:4.23126984;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path3510"
+ sodipodi:cx="369.5"
+ sodipodi:cy="316.09448"
+ sodipodi:rx="27.5"
+ sodipodi:ry="7"
+ d="M 397,316.09448 A 27.5,7 0 1 1 342,316.09448 A 27.5,7 0 1 1 397,316.09448 z"
+ transform="matrix(0,0.30778,-0.5642633,0,828.66499,563.5944)" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path3510"
+ id="use3544"
+ transform="translate(0.5000005,-17.23511)"
+ width="1052.3622"
+ height="744.09448" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:2.38492584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path3584"
+ sodipodi:cx="237.5"
+ sodipodi:cy="366.09448"
+ sodipodi:rx="8.5"
+ sodipodi:ry="8"
+ d="M 246,366.09448 A 8.5,8 0 1 1 229,366.09448 A 8.5,8 0 1 1 246,366.09448 z"
+ transform="matrix(1.7798114,-4.2997512e-2,1.3318941e-2,0.5513151,196.65666,476.1443)" />
+ <path
+ style="fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3.49756980000000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ d="M 423.2231,281.1169 C 502.67948,283.47026 574.8361,283.42778 668.97714,281.1169 C 668.97714,281.1169 670.77663,271.99598 668.97714,269.5402 C 559.46065,250.8302 423.2231,265.08614 423.2231,269.5402 L 423.2231,281.1169 z"
+ id="path3469"
+ sodipodi:nodetypes="cccsc" />
+ <rect
+ style="opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3408"
+ width="3.4280596"
+ height="29.611124"
+ x="709.89148"
+ y="-14.462622"
+ transform="matrix(0.9327494,0.3605254,-0.3633626,0.9316478,0,0)" />
+ <rect
+ style="opacity:1;fill:url(#linearGradient3416);fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:2.99999928;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3376"
+ width="48.499989"
+ height="8.5"
+ x="444.56302"
+ y="252.39224"
+ transform="matrix(0.9999952,3.0887776e-3,-3.0887776e-3,0.9999952,0,0)" />
+ <path
+ style="fill:url(#linearGradient3972);fill-opacity:1;fill-rule:evenodd;stroke:#323232;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 509,277.62139 C 509,277.62139 547.41409,235.70896 524,232.62139 L 615,244.62139 L 615,279.62139 L 509,277.62139 z"
+ id="path3952"
+ sodipodi:nodetypes="csccc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:url(#radialGradient3662);fill-opacity:1;fill-rule:nonzero;stroke:#41526b;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path3654"
+ sodipodi:cx="656.19507"
+ sodipodi:cy="541.15485"
+ sodipodi:rx="12.727922"
+ sodipodi:ry="16.263456"
+ d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z"
+ transform="matrix(0.5187874,0,0,0.3968421,374.8524,387.30025)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:url(#radialGradient3668);fill-opacity:1;fill-rule:nonzero;stroke:#41526b;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path3666"
+ sodipodi:cx="656.19507"
+ sodipodi:cy="541.15485"
+ sodipodi:rx="12.727922"
+ sodipodi:ry="16.263456"
+ d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z"
+ transform="matrix(0.5734968,0,0,0.4386917,316.52295,315.62837)" />
+ <path
+ transform="matrix(0.8598866,0,0,0.5637407,192.52282,220.77351)"
+ d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z"
+ sodipodi:ry="16.263456"
+ sodipodi:rx="12.727922"
+ sodipodi:cy="541.15485"
+ sodipodi:cx="656.19507"
+ id="path3670"
+ style="opacity:1;fill:url(#radialGradient3672);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.90000010000000020;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:url(#radialGradient3676);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.90000010000000020;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path3674"
+ sodipodi:cx="656.19507"
+ sodipodi:cy="541.15485"
+ sodipodi:rx="12.727922"
+ sodipodi:ry="16.263456"
+ d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z"
+ transform="matrix(0.7435991,0,0,0.6264519,225.8301,127.83701)" />
+ <g
+ id="g3759"
+ transform="matrix(0.8830571,0,0,0.8830571,104.83144,103.2985)">
+ <path
+ d="M 523.9661,469.73706 A 7.7781744,34.648232 0 1 1 508.40975,469.73706 A 7.7781744,34.648232 0 1 1 523.9661,469.73706 z"
+ sodipodi:ry="34.648232"
+ sodipodi:rx="7.7781744"
+ sodipodi:cy="469.73706"
+ sodipodi:cx="516.18793"
+ id="path3682"
+ style="opacity:1;fill:url(#linearGradient3772);fill-opacity:1;fill-rule:nonzero;stroke:#272727;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <g
+ id="g3754">
+ <rect
+ style="opacity:1;fill:url(#linearGradient3774);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3716"
+ width="33.58757"
+ height="59.927299"
+ x="498.86386"
+ y="497.84454" />
+ <path
+ style="fill:url(#linearGradient3776);fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 523.35045,482.89424 C 523.35045,482.89424 532.31256,488.20203 532.02344,500.14638 C 531.73431,512.09072 531.73431,511.73417 531.73431,511.73417 C 531.73431,511.73417 520.70627,493.83104 519.26887,499.77636 L 523.35045,482.89424 z"
+ id="path3704"
+ sodipodi:nodetypes="cscsc" />
+ <path
+ sodipodi:nodetypes="cscsc"
+ id="path3706"
+ d="M 508.50327,482.89424 C 508.50327,482.89424 499.54116,488.20203 499.83028,500.14638 C 500.11941,512.09072 500.11941,511.73417 500.11941,511.73417 C 500.11941,511.73417 511.14745,493.83104 512.58485,499.77636 L 508.50327,482.89424 z"
+ style="fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ </g>
+ <g
+ transform="matrix(0.8830571,0,0,0.8830571,192.45885,-66.370546)"
+ id="g3778">
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:url(#linearGradient3790);fill-opacity:1;fill-rule:nonzero;stroke:#272727;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path3780"
+ sodipodi:cx="516.18793"
+ sodipodi:cy="469.73706"
+ sodipodi:rx="7.7781744"
+ sodipodi:ry="34.648232"
+ d="M 523.9661,469.73706 A 7.7781744,34.648232 0 1 1 508.40975,469.73706 A 7.7781744,34.648232 0 1 1 523.9661,469.73706 z" />
+ <g
+ id="g3782">
+ <rect
+ y="497.84454"
+ x="498.86386"
+ height="59.927299"
+ width="33.58757"
+ id="rect3784"
+ style="opacity:1;fill:url(#linearGradient3792);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cscsc"
+ id="path3786"
+ d="M 523.35045,482.89424 C 523.35045,482.89424 532.31256,488.20203 532.02344,500.14638 C 531.73431,512.09072 531.73431,511.73417 531.73431,511.73417 C 531.73431,511.73417 520.70627,493.83104 519.26887,499.77636 L 523.35045,482.89424 z"
+ style="fill:url(#linearGradient3794);fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 508.50327,482.89424 C 508.50327,482.89424 499.54116,488.20203 499.83028,500.14638 C 500.11941,512.09072 500.11941,511.73417 500.11941,511.73417 C 500.11941,511.73417 511.14745,493.83104 512.58485,499.77636 L 508.50327,482.89424 z"
+ id="path3788"
+ sodipodi:nodetypes="cscsc" />
+ </g>
+ </g>
+ <path
+ transform="matrix(0.4292897,0,0,0.3283816,384.32775,481.20689)"
+ d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z"
+ sodipodi:ry="16.263456"
+ sodipodi:rx="12.727922"
+ sodipodi:cy="541.15485"
+ sodipodi:cx="656.19507"
+ id="path3802"
+ style="opacity:1;fill:url(#radialGradient3804);fill-opacity:1;fill-rule:nonzero;stroke:#41526b;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:url(#radialGradient3808);fill-opacity:1;fill-rule:nonzero;stroke:#41526b;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path3806"
+ sodipodi:cx="656.19507"
+ sodipodi:cy="541.15485"
+ sodipodi:rx="12.727922"
+ sodipodi:ry="16.263456"
+ d="M 668.92299,541.15485 A 12.727922,16.263456 0 1 1 643.46715,541.15485 A 12.727922,16.263456 0 1 1 668.92299,541.15485 z"
+ transform="matrix(0.5842998,0,0,0.4469553,299.7804,369.91514)" />
+ <path
+ style="fill:#ad8b00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 1059.5,736.57373 C 786.5,730.53352 912.51207,693.32637 768.5,736.53352 C 750.7005,741.87381 560.38464,722.59661 552.5,736.53352 C 528.68395,778.63085 223.94216,703.33865 182.5,727.16444 C 179.5,728.88919 160.53732,723.88477 135.5,730.90332 C 98.830356,741.18268 82.5,725.67603 43.5,731.71624 C 4.5,737.75645 0.5,733.72965 0.5,733.72965 L -6.5,747.98302 L 1049.5,747.31188 L 1059.5,736.57373 z"
+ id="path3828"
+ sodipodi:nodetypes="cssssscccc" />
+ <rect
+ style="opacity:1;fill:url(#linearGradient5103);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3448"
+ width="1053.5891"
+ height="67.882248"
+ x="-0.29455566"
+ y="274.57559" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path3519"
+ d="M 428,343.85222 C 428,343.85222 457.01739,315.41439 470,315.41439 C 481.98261,313.04457 634.13054,311.73511 652,317.41962 C 661.13441,320.56943 664.46012,324.9477 666,343.85222 C 600.25603,336.72647 497.8192,336.4719 428,343.85222 z"
+ style="opacity:0.43933058;fill:url(#linearGradient3521);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.0999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:url(#linearGradient3948);fill-opacity:1;fill-rule:evenodd;stroke:#545454;stroke-width:3.0999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 428,276.62139 C 428,276.62139 457.01739,315.62139 470,315.62139 C 481.98261,318.87139 634.13054,320.6672 652,312.87139 C 661.13441,308.55171 664.46012,302.54729 666,276.62139 C 600.25603,286.39373 497.8192,286.74286 428,276.62139 z"
+ id="path3938"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#dedede;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ d="M 466.00273,263.08289 L 484.25264,263.13926 L 494.7163,274.92164 L 465.96644,274.83284 L 466.00273,263.08289 z"
+ id="rect3378"
+ sodipodi:nodetypes="ccccc" />
+ <rect
+ style="opacity:1;fill:url(#linearGradient3990);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3974"
+ width="13.5"
+ height="17"
+ x="537.75"
+ y="251.2464"
+ inkscape:transform-center-x="30" />
+ <rect
+ inkscape:transform-center-x="30"
+ y="251.2464"
+ x="582.5"
+ height="17"
+ width="13.5"
+ id="rect3992"
+ style="opacity:1;fill:url(#linearGradient3994);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:#dedede;fill-opacity:1;fill-rule:nonzero;stroke:#484848;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ d="M 422.25,268.87139 C 487.33333,277.37139 573.16667,279.87139 668.5,268.87139 C 668.5,268.87139 670.30312,275.56827 668.5,277.37139 C 558.76249,291.1089 422.25,280.64171 422.25,277.37139 L 422.25,268.87139 z"
+ id="rect2558"
+ sodipodi:nodetypes="cccsc" />
+ <rect
+ style="opacity:1;fill:#c1c1c1;fill-opacity:1;fill-rule:nonzero;stroke:#404040;stroke-width:3.0365274;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2569"
+ width="94.427879"
+ height="7.236649"
+ x="546.39832"
+ y="177.10637"
+ transform="matrix(0.9947793,0.1020501,-0.1079723,0.9941539,0,0)" />
+ <rect
+ inkscape:transform-center-x="30"
+ y="251.2464"
+ x="559.875"
+ height="17"
+ width="13.5"
+ id="rect3385"
+ style="opacity:1;fill:url(#linearGradient3387);fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ id="g3401"
+ transform="matrix(0.9246214,0.3808874,-0.3808874,0.9246214,113.30125,-193.16902)"
+ inkscape:transform-center-x="17.590385"
+ inkscape:transform-center-y="-15.415449">
+ <rect
+ inkscape:transform-center-y="-43.888889"
+ transform="matrix(0,1,-1,0,0,0)"
+ style="opacity:1;fill:#b20000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3389"
+ width="19.75"
+ height="27.75"
+ x="193.34448"
+ y="-709" />
+ <rect
+ y="200.59448"
+ x="681.5"
+ height="5.75"
+ width="27.25"
+ id="rect3393"
+ style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ y="193.59448"
+ x="691.25"
+ height="19.5"
+ width="5.75"
+ id="rect3395"
+ style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ y="202.34448"
+ x="681.5"
+ height="2.5"
+ width="27.75"
+ id="rect3397"
+ style="opacity:1;fill:#000080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ y="193.59448"
+ x="692.5"
+ height="19.25"
+ width="3"
+ id="rect3399"
+ style="opacity:1;fill:#000080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <path
+ style="fill:#dcdcdc;fill-opacity:1;fill-rule:nonzero;stroke:#404040;stroke-width:3.03650045;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ d="M 529.42326,227.17914 L 616.35817,235.81552 L 618.07681,241.50986 L 524.14191,231.87348 L 529.42326,227.17914 z"
+ id="rect3466"
+ sodipodi:nodetypes="ccccc" />
+ <rect
+ style="opacity:1;fill:url(#linearGradient3426);fill-opacity:1;fill-rule:nonzero;stroke:#494949;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3418"
+ width="34.5"
+ height="14.5"
+ x="571.14081"
+ y="174.8026"
+ transform="matrix(0.997157,7.5351915e-2,-7.5351915e-2,0.997157,0,0)"
+ inkscape:transform-center-x="-8"
+ inkscape:transform-center-y="2" />
+ <g
+ id="mine"
+ transform="translate(971.11461,237.62715)"
+ inkscape:label="#g3441">
+ <path
+ transform="matrix(0.6341613,0,0,0.6341613,-18.521242,45.718192)"
+ d="M -167.5843,186.54079 A 31.466251,31.466251 0 1 1 -230.5168,186.54079 A 31.466251,31.466251 0 1 1 -167.5843,186.54079 z"
+ sodipodi:ry="31.466251"
+ sodipodi:rx="31.466251"
+ sodipodi:cy="186.54079"
+ sodipodi:cx="-199.05055"
+ id="path2586"
+ style="opacity:1;fill:url(#radialGradient3364);fill-opacity:1;stroke:#131313;stroke-width:3.54799318;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:nodetypes="ccss"
+ id="path3382"
+ d="M -155.20193,175.4167 C -157.60085,176.6451 -156.78074,184.26068 -156.78074,184.26068 C -156.78074,184.26068 -148.33787,181.58301 -148.57092,178.60053 C -148.74283,176.40051 -153.23774,174.41092 -155.20193,175.4167 z"
+ style="fill:url(#linearGradient3398);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccss"
+ id="path3400"
+ d="M -156.56354,153.84532 C -158.96246,152.61693 -158.14235,145.00135 -158.14235,145.00135 C -158.14235,145.00135 -149.69948,147.67902 -149.93253,150.66149 C -150.10444,152.86151 -154.59935,154.85111 -156.56354,153.84532 z"
+ style="fill:url(#linearGradient3402);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccss"
+ id="path3404"
+ d="M -133.88532,153.68678 C -131.48641,152.45838 -132.30652,144.8428 -132.30652,144.8428 C -132.30652,144.8428 -140.74938,147.52047 -140.51633,150.50295 C -140.34442,152.70297 -135.84951,154.69256 -133.88532,153.68678 z"
+ style="fill:url(#linearGradient3406);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccss"
+ id="path3408"
+ d="M -134.51948,175.55085 C -132.12057,176.77925 -132.94068,184.39483 -132.94068,184.39483 C -132.94068,184.39483 -141.38355,181.71716 -141.15049,178.73469 C -140.97858,176.53467 -136.48367,174.54507 -134.51948,175.55085 z"
+ style="fill:url(#linearGradient3410);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccss"
+ id="path3412"
+ d="M -161.25709,168.78221 C -163.22395,170.62484 -170.11427,165.85236 -170.11427,165.85236 C -170.11427,165.85236 -164.7408,160.23808 -162.01257,161.46538 C -160.00011,162.37068 -159.64667,167.27352 -161.25709,168.78221 z"
+ style="fill:url(#linearGradient3414);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccss"
+ id="path3416"
+ d="M -129.17068,169.10464 C -127.20382,170.94727 -120.3135,166.17478 -120.3135,166.17478 C -120.3135,166.17478 -125.68697,160.5605 -128.41519,161.7878 C -130.42766,162.69311 -130.7811,167.59595 -129.17068,169.10464 z"
+ style="fill:url(#linearGradient3418);fill-opacity:1;fill-rule:evenodd;stroke:#131313;stroke-width:2.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ transform="matrix(0.6341613,0,0,0.6341613,-61.039517,68.324922)"
+ d="M -126,151.21948 A 6.625,6.625 0 1 1 -139.25,151.21948 A 6.625,6.625 0 1 1 -126,151.21948 z"
+ sodipodi:ry="6.625"
+ sodipodi:rx="6.625"
+ sodipodi:cy="151.21948"
+ sodipodi:cx="-132.625"
+ id="path3426"
+ style="opacity:1;fill:url(#radialGradient3439);fill-opacity:1;stroke:#131313;stroke-width:3.54799318;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="arc" />
+ </g>
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/scalable/submarine.svg b/examples/animation/sub-attaq/pics/scalable/submarine.svg
new file mode 100644
index 0000000..8a0ffdd
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/submarine.svg
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg2594">
+ <defs
+ id="defs2596">
+ <linearGradient
+ id="linearGradient3345">
+ <stop
+ id="stop3348"
+ style="stop-color:#898989;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3350"
+ style="stop-color:#9ea1a2;stop-opacity:1"
+ offset="0.44021741" />
+ <stop
+ id="stop3352"
+ style="stop-color:#bbbdbf;stop-opacity:1"
+ offset="0.56799388" />
+ <stop
+ id="stop3354"
+ style="stop-color:#f0f1f2;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="510.99884"
+ y1="161.99408"
+ x2="396.48914"
+ y2="161.99408"
+ id="linearGradient3311"
+ xlink:href="#linearGradient3345"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.466978,0,0,0.4500435,231.58508,159.95135)" />
+ <linearGradient
+ id="linearGradient3532">
+ <stop
+ id="stop3534"
+ style="stop-color:#545454;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3536"
+ style="stop-color:#848788;stop-opacity:1"
+ offset="0.44021741" />
+ <stop
+ id="stop3538"
+ style="stop-color:#9ca0a2;stop-opacity:1"
+ offset="0.56799388" />
+ <stop
+ id="stop3540"
+ style="stop-color:#565d60;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="525"
+ y1="371.09448"
+ x2="525"
+ y2="395.09448"
+ id="linearGradient3520"
+ xlink:href="#linearGradient3532"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.5865192,0,0,0.2518015,219.30885,192.6957)" />
+ <linearGradient
+ id="linearGradient3227">
+ <stop
+ id="stop3229"
+ style="stop-color:#444444;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3232"
+ style="stop-color:#b0b0b0;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="543.5"
+ y1="205.19257"
+ x2="587.52002"
+ y2="205.19257"
+ id="linearGradient3812"
+ xlink:href="#linearGradient3227"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1223608,0,0,0.3849769,-137.93938,185.11074)" />
+ <linearGradient
+ id="linearGradient3167">
+ <stop
+ id="stop3169"
+ style="stop-color:#464646;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3345"
+ style="stop-color:#848788;stop-opacity:1"
+ offset="0.44021741" />
+ <stop
+ id="stop3347"
+ style="stop-color:#9ca0a2;stop-opacity:1"
+ offset="0.56799388" />
+ <stop
+ id="stop3171"
+ style="stop-color:#b5babd;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="443.95602"
+ y1="315.31854"
+ x2="443.95602"
+ y2="247.85609"
+ id="linearGradient3175"
+ xlink:href="#linearGradient3167"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4908502,0,0,0.4579593,230.56224,161.8228)" />
+ <linearGradient
+ id="linearGradient3421">
+ <stop
+ id="stop3423"
+ style="stop-color:#444444;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3425"
+ style="stop-color:#444444;stop-opacity:0"
+ offset="1" />
+ </linearGradient>
+ <radialGradient
+ cx="432.33429"
+ cy="233.80295"
+ r="59.056835"
+ fx="432.33429"
+ fy="233.80295"
+ id="radialGradient3339"
+ xlink:href="#linearGradient3421"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.4181493,0,0,0.1282619,265.67128,239.85868)" />
+ <linearGradient
+ id="linearGradient3435">
+ <stop
+ id="stop3437"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3439"
+ style="stop-color:#c0c0c0;stop-opacity:0"
+ offset="1" />
+ </linearGradient>
+ <radialGradient
+ cx="290.5"
+ cy="244.34448"
+ r="37.5"
+ fx="290.5"
+ fy="244.34448"
+ id="radialGradient3441"
+ xlink:href="#linearGradient3435"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.8202102,0.8202102,-0.7960458,0.7960458,246.73838,-189.686)" />
+ </defs>
+ <g
+ id="submarine">
+ <rect
+ width="10.557344"
+ height="6.0432386"
+ x="521.95276"
+ y="286.13785"
+ id="rect3512"
+ style="opacity:1;fill:url(#linearGradient3520);fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:0.56879884;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 472.62489,271.38195 C 472.62489,271.38195 533.23236,235.19412 518.64167,256.75283 C 504.05098,278.31152 504.05098,278.31152 504.05098,278.31152 L 472.62489,271.38195 z"
+ id="path2455"
+ style="fill:url(#linearGradient3812);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.77744257;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 364.84606,263.41905 C 322.73174,271.36528 338.10857,300.23647 381.79153,305.97905 C 431.25896,312.48206 448.02709,310.71241 484.92494,305.97905 C 537.1851,299.27497 537.2581,271.48536 484.92494,262.95644 C 433.55798,254.58499 395.6858,257.60014 364.84606,263.41905 z"
+ id="path2385"
+ style="fill:url(#linearGradient3175);fill-opacity:1;fill-rule:evenodd;stroke:#393939;stroke-width:1.90693891;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 421.75698,267.81211 C 428.13994,285.12832 488.00064,276.42836 466.51218,262.27195 C 466.51218,262.27195 422.9096,268.31187 421.75698,267.81211 z"
+ id="path3403"
+ style="fill:url(#radialGradient3339);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 416.97069,261.60997 C 416.97069,276.46141 463.19914,276.0068 463.19914,261.15536 L 463.19914,255.76162 C 463.19914,240.91094 416.97069,233.57552 416.97069,248.4262 L 416.97069,261.60997 z"
+ id="path3291"
+ style="fill:url(#linearGradient3311);fill-opacity:1;fill-rule:evenodd;stroke:#2d2d2d;stroke-width:2.07042313;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 341,263.09448 A 37.5,40 0 1 1 266,263.09448 A 37.5,40 0 1 1 341,263.09448 z"
+ transform="matrix(0.692163,0,1.4106583e-2,0.289185,154.89061,202.07342)"
+ id="path3433"
+ style="opacity:1;fill:url(#radialGradient3441);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.227;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 397,316.09448 A 27.5,7 0 1 1 342,316.09448 A 27.5,7 0 1 1 397,316.09448 z"
+ transform="matrix(0.5642633,0,0,0.5642633,227.60762,70.172035)"
+ id="path3458"
+ style="opacity:1;fill:#444444;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.06500006;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 397,316.09448 A 27.5,7 0 1 1 342,316.09448 A 27.5,7 0 1 1 397,316.09448 z"
+ transform="matrix(0,0.30778,-0.5642633,0,708.24166,183.29531)"
+ id="path3510"
+ style="opacity:1;fill:#444444;fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:4.23126984;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <use
+ transform="translate(0.5000044,-17.235115)"
+ id="use3544"
+ x="0"
+ y="0"
+ width="1052.3622"
+ height="744.09448"
+ xlink:href="#path3510" />
+ <path
+ d="M 246,366.09448 A 8.5,8 0 1 1 229,366.09448 A 8.5,8 0 1 1 246,366.09448 z"
+ transform="matrix(1.7798114,-4.2997512e-2,1.3318941e-2,0.5513151,76.233334,95.845205)"
+ id="path3584"
+ style="opacity:1;fill:#787878;fill-opacity:1;fill-rule:nonzero;stroke:#1b1e1f;stroke-width:2.38492584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/scalable/surface.svg b/examples/animation/sub-attaq/pics/scalable/surface.svg
new file mode 100644
index 0000000..40ed239
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/surface.svg
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg2685">
+ <defs
+ id="defs2687">
+ <linearGradient
+ id="linearGradient5097">
+ <stop
+ id="stop5099"
+ style="stop-color:#19a2db;stop-opacity:0"
+ offset="0" />
+ <stop
+ id="stop5109"
+ style="stop-color:#1379a7;stop-opacity:0.49803922"
+ offset="0.30000001" />
+ <stop
+ id="stop5101"
+ style="stop-color:#0e5173;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="590.84674"
+ y1="274.57559"
+ x2="590.84674"
+ y2="334.01376"
+ id="linearGradient5103"
+ xlink:href="#linearGradient5097"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-172.21428,209.55976)"
+ spreadMethod="pad" />
+ </defs>
+ <g
+ id="layer1">
+ <rect
+ width="1053.5891"
+ height="67.882248"
+ x="-172.50883"
+ y="484.13535"
+ id="rect3448"
+ style="opacity:1;fill:url(#linearGradient5103);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/scalable/torpedo.svg b/examples/animation/sub-attaq/pics/scalable/torpedo.svg
new file mode 100644
index 0000000..48e429d
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/scalable/torpedo.svg
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.0"
+ width="744.09448"
+ height="1052.3622"
+ id="svg2584">
+ <defs
+ id="defs2586">
+ <linearGradient
+ id="linearGradient3708">
+ <stop
+ id="stop3710"
+ style="stop-color:#202020;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3712"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="518.26996"
+ y1="497.31476"
+ x2="533.02924"
+ y2="497.31476"
+ id="linearGradient3776"
+ xlink:href="#linearGradient3708"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient3718">
+ <stop
+ id="stop3720"
+ style="stop-color:#bcbcbc;stop-opacity:0.28169015"
+ offset="0" />
+ <stop
+ id="stop3722"
+ style="stop-color:#bcbcbc;stop-opacity:0"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="516.89508"
+ y1="503.50137"
+ x2="516.89508"
+ y2="543.80646"
+ id="linearGradient3774"
+ xlink:href="#linearGradient3718"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9947644,0,0,1.3346457,2.7877039,-166.60153)" />
+ <linearGradient
+ id="linearGradient3692">
+ <stop
+ id="stop3694"
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0" />
+ <stop
+ id="stop3696"
+ style="stop-color:#b6b6b6;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ x1="506.95975"
+ y1="469.73706"
+ x2="525.41608"
+ y2="469.73706"
+ id="linearGradient3772"
+ xlink:href="#linearGradient3692"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ x1="506.95975"
+ y1="469.73706"
+ x2="525.41608"
+ y2="469.73706"
+ id="linearGradient2403"
+ xlink:href="#linearGradient3692"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ x1="516.89508"
+ y1="503.50137"
+ x2="516.89508"
+ y2="543.80646"
+ id="linearGradient2405"
+ xlink:href="#linearGradient3718"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9947644,0,0,1.3346457,2.7877039,-166.60153)" />
+ <linearGradient
+ x1="518.26996"
+ y1="497.31476"
+ x2="533.02924"
+ y2="497.31476"
+ id="linearGradient2407"
+ xlink:href="#linearGradient3708"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <g
+ transform="translate(-128.69958,6.6568748)"
+ id="torpedo">
+ <g
+ transform="matrix(0.8830571,0,0,0.8830571,-119.78327,177.67947)"
+ id="g3525">
+ <path
+ d="M 523.9661,469.73706 A 7.7781744,34.648232 0 1 1 508.40975,469.73706 A 7.7781744,34.648232 0 1 1 523.9661,469.73706 z"
+ id="path3682"
+ style="opacity:1;fill:url(#linearGradient2403);fill-opacity:1;fill-rule:nonzero;stroke:#272727;stroke-width:2.9000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ id="g3754">
+ <rect
+ width="33.58757"
+ height="59.927299"
+ x="498.86386"
+ y="497.84454"
+ id="rect3716"
+ style="opacity:1;fill:url(#linearGradient2405);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 523.35045,482.89424 C 523.35045,482.89424 532.31256,488.20203 532.02344,500.14638 C 531.73431,512.09072 531.73431,511.73417 531.73431,511.73417 C 531.73431,511.73417 520.70627,493.83104 519.26887,499.77636 L 523.35045,482.89424 z"
+ id="path3704"
+ style="fill:url(#linearGradient2407);fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 508.50327,482.89424 C 508.50327,482.89424 499.54116,488.20203 499.83028,500.14638 C 500.11941,512.09072 500.11941,511.73417 500.11941,511.73417 C 500.11941,511.73417 511.14745,493.83104 512.58485,499.77636 L 508.50327,482.89424 z"
+ id="path3706"
+ style="fill:#bcbcbc;fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.99788344;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/examples/animation/sub-attaq/pics/small/background.png b/examples/animation/sub-attaq/pics/small/background.png
new file mode 100644
index 0000000..5ad3db6
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/small/background.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/small/boat.png b/examples/animation/sub-attaq/pics/small/boat.png
new file mode 100644
index 0000000..114ccc3
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/small/boat.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/small/bomb.png b/examples/animation/sub-attaq/pics/small/bomb.png
new file mode 100644
index 0000000..3af5f2f
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/small/bomb.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/small/submarine.png b/examples/animation/sub-attaq/pics/small/submarine.png
new file mode 100644
index 0000000..0c0c350
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/small/submarine.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/small/surface.png b/examples/animation/sub-attaq/pics/small/surface.png
new file mode 100644
index 0000000..06d0e47
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/small/surface.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/small/torpedo.png b/examples/animation/sub-attaq/pics/small/torpedo.png
new file mode 100644
index 0000000..f9c2687
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/small/torpedo.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/welcome/logo-a.png b/examples/animation/sub-attaq/pics/welcome/logo-a.png
new file mode 100644
index 0000000..67dd76d
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/welcome/logo-a.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/welcome/logo-a2.png b/examples/animation/sub-attaq/pics/welcome/logo-a2.png
new file mode 100644
index 0000000..17668b0
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/welcome/logo-a2.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/welcome/logo-b.png b/examples/animation/sub-attaq/pics/welcome/logo-b.png
new file mode 100644
index 0000000..cf6c045
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/welcome/logo-b.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/welcome/logo-dash.png b/examples/animation/sub-attaq/pics/welcome/logo-dash.png
new file mode 100644
index 0000000..219233c
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/welcome/logo-dash.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/welcome/logo-excl.png b/examples/animation/sub-attaq/pics/welcome/logo-excl.png
new file mode 100644
index 0000000..8dd0a2e
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/welcome/logo-excl.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/welcome/logo-q.png b/examples/animation/sub-attaq/pics/welcome/logo-q.png
new file mode 100644
index 0000000..86e588d
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/welcome/logo-q.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/welcome/logo-s.png b/examples/animation/sub-attaq/pics/welcome/logo-s.png
new file mode 100644
index 0000000..7b6a36e
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/welcome/logo-s.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/welcome/logo-t.png b/examples/animation/sub-attaq/pics/welcome/logo-t.png
new file mode 100644
index 0000000..b2e3526
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/welcome/logo-t.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/welcome/logo-t2.png b/examples/animation/sub-attaq/pics/welcome/logo-t2.png
new file mode 100644
index 0000000..b11a778
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/welcome/logo-t2.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pics/welcome/logo-u.png b/examples/animation/sub-attaq/pics/welcome/logo-u.png
new file mode 100644
index 0000000..24eede8
--- /dev/null
+++ b/examples/animation/sub-attaq/pics/welcome/logo-u.png
Binary files differ
diff --git a/examples/animation/sub-attaq/pixmapitem.cpp b/examples/animation/sub-attaq/pixmapitem.cpp
new file mode 100644
index 0000000..aa8b552
--- /dev/null
+++ b/examples/animation/sub-attaq/pixmapitem.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//Own
+#include "pixmapitem.h"
+
+//Qt
+#include <QDir>
+
+PixmapItem::PixmapItem(const QString &fileName,GraphicsScene::Mode mode, QGraphicsItem * parent) : QGraphicsPixmapItem(parent),name(fileName)
+{
+ loadPixmap(mode);
+}
+
+void PixmapItem::loadPixmap(GraphicsScene::Mode mode)
+{
+ if (mode == GraphicsScene::Big)
+ setPixmap(":/big/" + name);
+ else
+ setPixmap(":/small/" + name);
+}
diff --git a/examples/animation/sub-attaq/pixmapitem.h b/examples/animation/sub-attaq/pixmapitem.h
new file mode 100644
index 0000000..f3c1a41
--- /dev/null
+++ b/examples/animation/sub-attaq/pixmapitem.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __PIXMAPITEM__H__
+#define __PIXMAPITEM__H__
+
+//Own
+#include "graphicsscene.h"
+
+//Qt
+#include <QGraphicsPixmapItem>
+
+class PixmapItem : public QGraphicsPixmapItem
+{
+public:
+ PixmapItem(const QString &fileName, GraphicsScene::Mode mode, QGraphicsItem * parent = 0);
+
+private:
+ void loadPixmap(GraphicsScene::Mode mode);
+
+ QString name;
+ QPixmap pixmap;
+};
+
+#endif //__PIXMAPITEM__H__
diff --git a/examples/animation/sub-attaq/states.cpp b/examples/animation/sub-attaq/states.cpp
new file mode 100644
index 0000000..32e0bb8
--- /dev/null
+++ b/examples/animation/sub-attaq/states.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//Own
+#include "states.h"
+#include "graphicsscene.h"
+#include "boat.h"
+#include "submarine.h"
+#include "torpedo.h"
+#include "animationmanager.h"
+
+//Qt
+#include <QMessageBox>
+#include <QGraphicsView>
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+#include "qstatemachine.h"
+#include "qkeyeventtransition.h"
+#include "qsignalevent.h"
+#include "qfinalstate.h"
+#else
+#include <QtCore/QStateMachine>
+#include <QtGui/QKeyEventTransition>
+#include <QtCore/QSignalEvent>
+#include <QFinalState>
+#endif
+
+PlayState::PlayState(GraphicsScene *scene, QState *parent)
+ : QState(parent),
+ scene(scene),
+ machine(0),
+ currentLevel(0),
+ score(0)
+{
+}
+
+PlayState::~PlayState()
+{
+}
+
+void PlayState::onEntry()
+{
+ //We are now playing?
+ if (machine) {
+ machine->stop();
+ scene->clearScene();
+ delete machine;
+ }
+
+ machine = new QStateMachine(this);
+
+ //This state is when player is playing
+ QState *playState = new QState(machine->rootState());
+
+ initializeLevel();
+
+ //This state is when the game is paused
+ PauseState *pauseState = new PauseState(scene, machine->rootState());
+
+ //We have one view, it receive the key press event
+ QKeyEventTransition *pressPplay = new QKeyEventTransition(scene->views().at(0), QEvent::KeyPress, Qt::Key_P);
+ pressPplay->setTargetState(pauseState);
+ QKeyEventTransition *pressPpause = new QKeyEventTransition(scene->views().at(0), QEvent::KeyPress, Qt::Key_P);
+ pressPpause->setTargetState(playState);
+
+ //Pause "P" is triggered, the player pause the game
+ playState->addTransition(pressPplay);
+
+ //To get back playing when the game has been paused
+ pauseState->addTransition(pressPpause);
+
+ //This state is when player have lost
+ LostState *lostState = new LostState(scene, this, machine->rootState());
+
+ //This state is when player have won
+ WinState *winState = new WinState(scene, this, machine->rootState());
+
+ //The boat has been destroyed then the game is finished
+ playState->addTransition(scene->boat, SIGNAL(boatExecutionFinished()),lostState);
+
+ //This transition check if we won or not
+ WinTransition *winTransition = new WinTransition(scene, this, winState);
+
+ //The boat has been destroyed then the game is finished
+ playState->addTransition(winTransition);
+
+ //This state is an animation when the score changed
+ UpdateScoreState *scoreState = new UpdateScoreState(this, machine->rootState());
+
+ //This transition update the score when a submarine die
+ UpdateScoreTransition *scoreTransition = new UpdateScoreTransition(scene, this, scoreState);
+
+ //The boat has been destroyed then the game is finished
+ playState->addTransition(scoreTransition);
+
+ //We go back to play state
+ scoreState->addFinishedTransition(playState);
+
+ //We start playing!!!
+ machine->setInitialState(playState);
+
+ //Final state
+ QFinalState *final = new QFinalState(machine->rootState());
+
+ //We win we should reach the final state
+ winState->addFinishedTransition(final);
+
+ //We lost we should reach the final state
+ lostState->addFinishedTransition(final);
+
+ machine->start();
+}
+
+void PlayState::initializeLevel()
+{
+ scene->boat = new Boat();
+ scene->addItem(scene->boat);
+ scene->setFocusItem(scene->boat,Qt::OtherFocusReason);
+ scene->boat->setPos(scene->width()/2, scene->sealLevel() - scene->boat->size().height());
+
+ GraphicsScene::LevelDescription currentLevelDescription = scene->levelsData.value(currentLevel);
+
+ for (int i = 0; i < currentLevelDescription.submarines.size(); ++i ) {
+
+ QPair<int,int> subContent = currentLevelDescription.submarines.at(i);
+ GraphicsScene::SubmarineDescription submarineDesc = scene->submarinesData.at(subContent.first);
+
+ for (int j = 0; j < subContent.second; ++j ) {
+ SubMarine *sub = new SubMarine(submarineDesc.type, submarineDesc.name, submarineDesc.points);
+ scene->addItem(sub);
+ int random = (qrand() % 15 + 1);
+ qreal x = random == 13 || random == 5 ? 0 : scene->width() - sub->size().width();
+ qreal y = scene->height() -(qrand() % 150 + 1) - sub->size().height();
+ sub->setPos(x,y);
+ sub->setCurrentDirection(x == 0 ? SubMarine::Right : SubMarine::Left);
+ sub->setCurrentSpeed(qrand() % 3 + 1);
+ }
+ }
+}
+
+/** Pause State */
+PauseState::PauseState(GraphicsScene *scene, QState *parent) : QState(parent),scene(scene)
+{
+}
+void PauseState::onEntry()
+{
+ AnimationManager::self()->pauseAll();
+ scene->boat->setEnabled(false);
+}
+void PauseState::onExit()
+{
+ AnimationManager::self()->resumeAll();
+ scene->boat->setEnabled(true);
+ scene->boat->setFocus();
+}
+
+/** Lost State */
+LostState::LostState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game)
+{
+}
+
+void LostState::onEntry()
+{
+ //The message to display
+ QString message = QString("You lose on level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score);
+
+ //We set the level back to 0
+ game->currentLevel = 0;
+
+ //We set the score back to 0
+ game->score = 0;
+
+ //We clear the scene
+ scene->clearScene();
+
+ //we have only one view
+ QMessageBox::information(scene->views().at(0),"You lose",message);
+}
+
+/** Win State */
+WinState::WinState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game)
+{
+}
+
+void WinState::onEntry()
+{
+ //We clear the scene
+ scene->clearScene();
+
+ QString message;
+ if (scene->levelsData.size() - 1 != game->currentLevel) {
+ message = QString("You win the level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score);
+ //We increment the level number
+ game->currentLevel++;
+ } else {
+ message = QString("You finish the game on level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score);
+ //We set the level back to 0
+ game->currentLevel = 0;
+ //We set the score back to 0
+ game->score = 0;
+ }
+
+ //we have only one view
+ QMessageBox::information(scene->views().at(0),"You win",message);
+}
+
+/** UpdateScore State */
+UpdateScoreState::UpdateScoreState(PlayState *game, QState *parent) : QAnimationState(parent)
+{
+ this->game = game;
+}
+void UpdateScoreState::onEntry()
+{
+ //### Make a nice anim to update the score in the scene
+ QAnimationState::onEntry();
+}
+
+/** Win transition */
+UpdateScoreTransition::UpdateScoreTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target)
+ : QSignalTransition(scene,SIGNAL(subMarineDestroyed(int)), QList<QAbstractState*>() << target),
+ game(game)
+{
+}
+
+bool UpdateScoreTransition::eventTest(QEvent *event) const
+{
+ if (!QSignalTransition::eventTest(event))
+ return false;
+ else {
+ QSignalEvent *se = static_cast<QSignalEvent*>(event);
+ game->score += se->arguments().at(0).toInt();
+ return true;
+ }
+}
+
+/** Win transition */
+WinTransition::WinTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target)
+ : QSignalTransition(scene,SIGNAL(allSubMarineDestroyed(int)), QList<QAbstractState*>() << target),
+ game(game)
+{
+}
+
+bool WinTransition::eventTest(QEvent *event) const
+{
+ if (!QSignalTransition::eventTest(event))
+ return false;
+ else {
+ QSignalEvent *se = static_cast<QSignalEvent*>(event);
+ game->score += se->arguments().at(0).toInt();
+ return true;
+ }
+}
diff --git a/examples/animation/sub-attaq/states.h b/examples/animation/sub-attaq/states.h
new file mode 100644
index 0000000..1001827
--- /dev/null
+++ b/examples/animation/sub-attaq/states.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef STATES_H
+#define STATES_H
+
+//Qt
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+#include "qstate.h"
+#include "qsignaltransition.h"
+#include "qanimationstate.h"
+#include "qpropertyanimation.h"
+#else
+#include <QState>
+#include <QSignalTransition>
+#include <QAnimationState>
+#include <QPropertyAnimation>
+#endif
+#include <QSet>
+
+class GraphicsScene;
+class Boat;
+class SubMarine;
+class QStateMachine;
+
+class PlayState : public QState
+{
+public:
+ PlayState(GraphicsScene *scene, QState *parent = 0);
+ ~PlayState();
+ void initializeLevel();
+
+ protected:
+ void onEntry();
+
+private :
+ GraphicsScene *scene;
+ QStateMachine *machine;
+ int currentLevel;
+ int score;
+ QState *parallelChild;
+
+ friend class UpdateScoreState;
+ friend class UpdateScoreTransition;
+ friend class WinTransition;
+ friend class WinState;
+ friend class LostState;
+};
+
+class PauseState : public QState
+{
+public:
+ PauseState(GraphicsScene *scene, QState *parent = 0);
+
+protected:
+ void onEntry();
+ void onExit();
+private :
+ GraphicsScene *scene;
+ Boat *boat;
+};
+
+class LostState : public QState
+{
+public:
+ LostState(GraphicsScene *scene, PlayState *game, QState *parent = 0);
+
+protected:
+ void onEntry();
+private :
+ GraphicsScene *scene;
+ PlayState *game;
+};
+
+class WinState : public QState
+{
+public:
+ WinState(GraphicsScene *scene, PlayState *game, QState *parent = 0);
+
+protected:
+ void onEntry();
+private :
+ GraphicsScene *scene;
+ PlayState *game;
+};
+
+class UpdateScoreState : public QAnimationState
+{
+public:
+ UpdateScoreState(PlayState *game, QState *parent);
+protected:
+ void onEntry();
+private:
+ QPropertyAnimation *scoreAnimation;
+ PlayState *game;
+};
+
+//These transtion is used to update the score
+class UpdateScoreTransition : public QSignalTransition
+{
+public:
+ UpdateScoreTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target);
+protected:
+ virtual bool eventTest(QEvent *event) const;
+private:
+ PlayState * game;
+};
+
+//These transtion test if we have won the game
+class WinTransition : public QSignalTransition
+{
+public:
+ WinTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target);
+protected:
+ virtual bool eventTest(QEvent *event) const;
+private:
+ PlayState * game;
+};
+
+#endif // STATES_H
diff --git a/examples/animation/sub-attaq/sub-attaq.pro b/examples/animation/sub-attaq/sub-attaq.pro
new file mode 100644
index 0000000..d8de6f5
--- /dev/null
+++ b/examples/animation/sub-attaq/sub-attaq.pro
@@ -0,0 +1,36 @@
+# #####################################################################
+# Automatically generated by qmake (2.01a) Thu Oct 9 10:53:30 2008
+# #####################################################################
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+QT+= xml
+contains(QT_CONFIG, opengl):QT += opengl
+
+# Input
+HEADERS += boat.h \
+ bomb.h \
+ mainwindow.h \
+ submarine.h \
+ torpedo.h \
+ pixmapitem.h \
+ graphicsscene.h \
+ animationmanager.h \
+ states.h \
+ boat_p.h \
+ submarine_p.h \
+ custompropertyanimation_p.h \
+ custompropertyanimation.h
+SOURCES += boat.cpp \
+ bomb.cpp \
+ main.cpp \
+ mainwindow.cpp \
+ submarine.cpp \
+ torpedo.cpp \
+ pixmapitem.cpp \
+ graphicsscene.cpp \
+ animationmanager.cpp \
+ states.cpp \
+ custompropertyanimation.cpp
+RESOURCES += subattaq.qrc
diff --git a/examples/animation/sub-attaq/subattaq.qrc b/examples/animation/sub-attaq/subattaq.qrc
new file mode 100644
index 0000000..c76f8ef
--- /dev/null
+++ b/examples/animation/sub-attaq/subattaq.qrc
@@ -0,0 +1,38 @@
+<RCC>
+ <qresource prefix="/" >
+ <file alias="all" >pics/scalable/sub-attaq.svg</file>
+ <file alias="submarine" >pics/scalable/submarine.svg</file>
+ <file alias="boat" >pics/scalable/boat.svg</file>
+ <file alias="torpedo" >pics/scalable/torpedo.svg</file>
+ <file alias="logo-s" >pics/welcome/logo-s.png</file>
+ <file alias="logo-u" >pics/welcome/logo-u.png</file>
+ <file alias="logo-b" >pics/welcome/logo-b.png</file>
+ <file alias="logo-dash" >pics/welcome/logo-dash.png</file>
+ <file alias="logo-a" >pics/welcome/logo-a.png</file>
+ <file alias="logo-t" >pics/welcome/logo-t.png</file>
+ <file alias="logo-t2" >pics/welcome/logo-t2.png</file>
+ <file alias="logo-a2" >pics/welcome/logo-a2.png</file>
+ <file alias="logo-q" >pics/welcome/logo-q.png</file>
+ <file alias="logo-excl" >pics/welcome/logo-excl.png</file>
+ <file alias="big/background" >pics/big/background.png</file>
+ <file alias="big/boat" >pics/big/boat.png</file>
+ <file alias="big/bomb" >pics/big/bomb.png</file>
+ <file alias="big/submarine" >pics/big/submarine.png</file>
+ <file alias="big/surface" >pics/big/surface.png</file>
+ <file alias="big/torpedo" >pics/big/torpedo.png</file>
+ <file alias="small/background" >pics/small/background.png</file>
+ <file alias="small/boat" >pics/small/boat.png</file>
+ <file alias="small/bomb" >pics/small/bomb.png</file>
+ <file alias="small/submarine" >pics/small/submarine.png</file>
+ <file alias="small/surface" >pics/small/surface.png</file>
+ <file alias="small/torpedo" >pics/small/torpedo.png</file>
+ <file alias="big/explosion/boat/step1" >pics/big/explosion/boat/step1.png</file>
+ <file alias="big/explosion/boat/step2" >pics/big/explosion/boat/step2.png</file>
+ <file alias="big/explosion/boat/step3" >pics/big/explosion/boat/step3.png</file>
+ <file alias="big/explosion/boat/step4" >pics/big/explosion/boat/step4.png</file>
+ <file alias="big/explosion/submarine/step1" >pics/big/explosion/submarine/step1.png</file>
+ <file alias="big/explosion/submarine/step2" >pics/big/explosion/submarine/step2.png</file>
+ <file alias="big/explosion/submarine/step3" >pics/big/explosion/submarine/step3.png</file>
+ <file alias="big/explosion/submarine/step4" >pics/big/explosion/submarine/step4.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/animation/sub-attaq/submarine.cpp b/examples/animation/sub-attaq/submarine.cpp
new file mode 100644
index 0000000..481c748
--- /dev/null
+++ b/examples/animation/sub-attaq/submarine.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//Own
+#include "submarine.h"
+#include "submarine_p.h"
+#include "torpedo.h"
+#include "pixmapitem.h"
+#include "graphicsscene.h"
+#include "animationmanager.h"
+#include "custompropertyanimation.h"
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+#include "qpropertyanimation.h"
+#include "qstatemachine.h"
+#include "qfinalstate.h"
+#include "qanimationstate.h"
+#include "qsequentialanimationgroup.h"
+#else
+#include <QPropertyAnimation>
+#include <QStateMachine>
+#include <QFinalState>
+#include <QAnimationState>
+#include <QSequentialAnimationGroup>
+#endif
+
+static QAbstractAnimation *setupDestroyAnimation(SubMarine *sub)
+{
+ QSequentialAnimationGroup *group = new QSequentialAnimationGroup(sub);
+#if QT_VERSION >=0x040500
+ PixmapItem *step1 = new PixmapItem(QString("explosion/submarine/step1"),GraphicsScene::Big, sub);
+ step1->setZValue(6);
+ PixmapItem *step2 = new PixmapItem(QString("explosion/submarine/step2"),GraphicsScene::Big, sub);
+ step2->setZValue(6);
+ PixmapItem *step3 = new PixmapItem(QString("explosion/submarine/step3"),GraphicsScene::Big, sub);
+ step3->setZValue(6);
+ PixmapItem *step4 = new PixmapItem(QString("explosion/submarine/step4"),GraphicsScene::Big, sub);
+ step4->setZValue(6);
+ step1->setOpacity(0);
+ step2->setOpacity(0);
+ step3->setOpacity(0);
+ step4->setOpacity(0);
+ CustomPropertyAnimation *anim1 = new CustomPropertyAnimation(sub);
+ anim1->setMemberFunctions((QGraphicsItem*)step1, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity);
+ anim1->setDuration(100);
+ anim1->setEndValue(1);
+ CustomPropertyAnimation *anim2 = new CustomPropertyAnimation(sub);
+ anim2->setMemberFunctions((QGraphicsItem*)step2, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity);
+ anim2->setDuration(100);
+ anim2->setEndValue(1);
+ CustomPropertyAnimation *anim3 = new CustomPropertyAnimation(sub);
+ anim3->setMemberFunctions((QGraphicsItem*)step3, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity);
+ anim3->setDuration(100);
+ anim3->setEndValue(1);
+ CustomPropertyAnimation *anim4 = new CustomPropertyAnimation(sub);
+ anim4->setMemberFunctions((QGraphicsItem*)step4, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity);
+ anim4->setDuration(100);
+ anim4->setEndValue(1);
+ group->addAnimation(anim1);
+ group->addAnimation(anim2);
+ group->addAnimation(anim3);
+ group->addAnimation(anim4);
+#else
+ // work around for a bug where we don't transition if the duration is zero.
+ QtPauseAnimation *anim = new QtPauseAnimation(group);
+ anim->setDuration(1);
+ group->addAnimation(anim);
+#endif
+ AnimationManager::self()->registerAnimation(group);
+ return group;
+}
+
+
+SubMarine::SubMarine(int type, const QString &name, int points, QGraphicsItem * parent, Qt::WindowFlags wFlags)
+ : QGraphicsWidget(parent,wFlags), subType(type), subName(name), subPoints(points), speed(0), direction(SubMarine::None)
+{
+ pixmapItem = new PixmapItem(QString("submarine"),GraphicsScene::Big, this);
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ setZValue(5);
+ setFlags(QGraphicsItem::ItemIsMovable);
+ resize(pixmapItem->boundingRect().width(),pixmapItem->boundingRect().height());
+ setTransformOrigin(boundingRect().center());
+
+ //We setup the state machine of the submarine
+ QStateMachine *machine = new QStateMachine(this);
+
+ //This state is when the boat is moving/rotating
+ QState *moving = new QState(machine->rootState());
+
+ //This state is when the boat is moving from left to right
+ MovementState *movement = new MovementState(this,moving);
+
+ //This state is when the boat is moving from left to right
+ ReturnState *rotation = new ReturnState(this,moving);
+
+ //This is the initial state of the moving root state
+ moving->setInitialState(movement);
+
+ movement->addTransition(this, SIGNAL(subMarineStateChanged()),moving);
+
+ //This is the initial state of the machine
+ machine->setInitialState(moving);
+
+ //End
+ QFinalState *final = new QFinalState(machine->rootState());
+
+ //If the moving animation is finished we move to the return state
+ movement->addFinishedTransition(rotation);
+
+ //If the return animation is finished we move to the moving state
+ rotation->addFinishedTransition(movement);
+
+ //This state play the destroyed animation
+ QAnimationState *destroyedState = new QAnimationState(machine->rootState());
+ destroyedState->addAnimation(setupDestroyAnimation(this));
+
+ //Play a nice animation when the submarine is destroyed
+ moving->addTransition(this, SIGNAL(subMarineDestroyed()),destroyedState);
+
+ //Transition to final state when the destroyed animation is finished
+ destroyedState->addFinishedTransition(final);
+
+ //The machine has finished to be executed, then the submarine is dead
+ connect(machine,SIGNAL(finished()),this, SIGNAL(subMarineExecutionFinished()));
+
+ machine->start();
+}
+
+int SubMarine::points()
+{
+ return subPoints;
+}
+
+void SubMarine::setCurrentDirection(SubMarine::Movement direction)
+{
+ if (this->direction == direction)
+ return;
+ if (direction == SubMarine::Right && this->direction == SubMarine::None) {
+ setYRotation(180);
+ }
+ this->direction = direction;
+}
+
+enum SubMarine::Movement SubMarine::currentDirection() const
+{
+ return direction;
+}
+
+void SubMarine::setCurrentSpeed(int speed)
+{
+ if (speed < 0 || speed > 3) {
+ qWarning("SubMarine::setCurrentSpeed : The speed is invalid");
+ }
+ this->speed = speed;
+ emit subMarineStateChanged();
+}
+
+int SubMarine::currentSpeed() const
+{
+ return speed;
+}
+
+void SubMarine::launchTorpedo(int speed)
+{
+ Torpedo * torp = new Torpedo();
+ GraphicsScene *scene = static_cast<GraphicsScene *>(this->scene());
+ scene->addItem(torp);
+ torp->setPos(x(), y());
+ torp->setCurrentSpeed(speed);
+ torp->launch();
+}
+
+void SubMarine::destroy()
+{
+ emit subMarineDestroyed();
+}
+
+int SubMarine::type() const
+{
+ return Type;
+}
diff --git a/examples/animation/sub-attaq/submarine.h b/examples/animation/sub-attaq/submarine.h
new file mode 100644
index 0000000..562b4cf
--- /dev/null
+++ b/examples/animation/sub-attaq/submarine.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __SUBMARINE__H__
+#define __SUBMARINE__H__
+
+//Qt
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+#include "qvariantanimation.h"
+#include "qgraphicswidget.h"
+#else
+#include <QVariantAnimation>
+#include <QGraphicsWidget>
+#endif
+
+class PixmapItem;
+
+class Torpedo;
+
+class SubMarine : public QGraphicsWidget
+{
+Q_OBJECT
+public:
+ enum Movement {
+ None = 0,
+ Left,
+ Right
+ };
+ enum { Type = UserType + 1 };
+ SubMarine(int type, const QString &name, int points, QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0);
+
+ int points();
+
+ void setCurrentDirection(Movement direction);
+ enum Movement currentDirection() const;
+
+ void setCurrentSpeed(int speed);
+ int currentSpeed() const;
+
+ void launchTorpedo(int speed);
+ void destroy();
+
+ virtual int type() const;
+
+Q_SIGNALS:
+ void subMarineDestroyed();
+ void subMarineExecutionFinished();
+ void subMarineStateChanged();
+
+private:
+ int subType;
+ QString subName;
+ int subPoints;
+ int speed;
+ Movement direction;
+ PixmapItem *pixmapItem;
+};
+
+#endif //__SUBMARINE__H__
diff --git a/examples/animation/sub-attaq/submarine_p.h b/examples/animation/sub-attaq/submarine_p.h
new file mode 100644
index 0000000..5aa84b6
--- /dev/null
+++ b/examples/animation/sub-attaq/submarine_p.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SUBMARINE_P_H
+#define SUBMARINE_P_H
+
+//Own
+#include "animationmanager.h"
+#include "submarine.h"
+
+//Qt
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+#include "qanimationstate.h"
+#include "qpropertyanimation.h"
+#else
+#include <QAnimationState>
+#include <QPropertyAnimation>
+#endif
+#include <QGraphicsScene>
+
+
+//This state is describing when the boat is moving right
+class MovementState : public QAnimationState
+{
+Q_OBJECT
+public:
+ MovementState(SubMarine *submarine, QState *parent = 0) : QAnimationState(parent)
+ {
+ movementAnimation = new QPropertyAnimation(submarine, "pos");
+ connect(movementAnimation,SIGNAL(valueChanged(const QVariant &)),this,SLOT(onAnimationMovementValueChanged(const QVariant &)));
+ addAnimation(movementAnimation);
+ AnimationManager::self()->registerAnimation(movementAnimation);
+ this->submarine = submarine;
+ }
+protected slots:
+ void onAnimationMovementValueChanged(const QVariant &)
+ {
+ if (qrand() % 200 + 1 == 3)
+ submarine->launchTorpedo(qrand() % 3 + 1);
+ }
+protected:
+ void onEntry()
+ {
+ if (submarine->currentDirection() == SubMarine::Left) {
+ movementAnimation->setEndValue(QPointF(0,submarine->y()));
+ movementAnimation->setDuration(submarine->x()/submarine->currentSpeed()*12);
+ }
+ else /*if (submarine->currentDirection() == SubMarine::Right)*/ {
+ movementAnimation->setEndValue(QPointF(submarine->scene()->width()-submarine->size().width(),submarine->y()));
+ movementAnimation->setDuration((submarine->scene()->width()-submarine->size().width()-submarine->x())/submarine->currentSpeed()*12);
+ }
+ movementAnimation->setStartValue(submarine->pos());
+ QAnimationState::onEntry();
+ }
+
+ void onExit()
+ {
+ movementAnimation->stop();
+ QAnimationState::onExit();
+ }
+private:
+ SubMarine *submarine;
+ QPropertyAnimation *movementAnimation;
+};
+
+//This state is describing when the boat is moving right
+class ReturnState : public QAnimationState
+{
+public:
+ ReturnState(SubMarine *submarine, QState *parent = 0) : QAnimationState(parent)
+ {
+ returnAnimation = new QPropertyAnimation(submarine, "yRotation");
+ AnimationManager::self()->registerAnimation(returnAnimation);
+ addAnimation(returnAnimation);
+ this->submarine = submarine;
+ }
+protected:
+ void onEntry()
+ {
+ returnAnimation->stop();
+ returnAnimation->setStartValue(submarine->yRotation());
+ returnAnimation->setEndValue(submarine->currentDirection() == SubMarine::Right ? 360. : 180.);
+ returnAnimation->setDuration(500);
+ QAnimationState::onEntry();
+ }
+
+ void onExit()
+ {
+ returnAnimation->stop();
+ submarine->currentDirection() == SubMarine::Right ? submarine->setCurrentDirection(SubMarine::Left) : submarine->setCurrentDirection(SubMarine::Right);
+ QAnimationState::onExit();
+ }
+private:
+ SubMarine *submarine;
+ QPropertyAnimation *returnAnimation;
+};
+
+#endif // SUBMARINE_P_H
diff --git a/examples/animation/sub-attaq/torpedo.cpp b/examples/animation/sub-attaq/torpedo.cpp
new file mode 100644
index 0000000..4964192
--- /dev/null
+++ b/examples/animation/sub-attaq/torpedo.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//Own
+#include "torpedo.h"
+#include "pixmapitem.h"
+#include "boat.h"
+#include "graphicsscene.h"
+#include "animationmanager.h"
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+#include "qpropertyanimation.h"
+#include "qstatemachine.h"
+#include "qfinalstate.h"
+#include "qanimationstate.h"
+#else
+#include <QPropertyAnimation>
+#include <QAnimationState>
+#include <QStateMachine>
+#include <QFinalState>
+#endif
+
+Torpedo::Torpedo(QGraphicsItem * parent, Qt::WindowFlags wFlags)
+ : QGraphicsWidget(parent,wFlags), currentSpeed(0), launchAnimation(0)
+{
+ pixmapItem = new PixmapItem(QString::fromLatin1("torpedo"),GraphicsScene::Big, this);
+ setZValue(2);
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ setFlags(QGraphicsItem::ItemIsMovable);
+ resize(pixmapItem->boundingRect().size());
+}
+
+void Torpedo::launch()
+{
+ launchAnimation = new QPropertyAnimation(this, "pos");
+ AnimationManager::self()->registerAnimation(launchAnimation);
+ launchAnimation->setEndValue(QPointF(x(),qobject_cast<GraphicsScene *>(scene())->sealLevel() - 15));
+ launchAnimation->setEasingCurve(QEasingCurve::InQuad);
+ launchAnimation->setDuration(y()/currentSpeed*10);
+ connect(launchAnimation,SIGNAL(valueChanged(const QVariant &)),this,SLOT(onAnimationLaunchValueChanged(const QVariant &)));
+
+ //We setup the state machine of the torpedo
+ QStateMachine *machine = new QStateMachine(this);
+
+ //This state is when the launch animation is playing
+ QAnimationState *launched = new QAnimationState(launchAnimation,machine->rootState());
+
+ machine->setInitialState(launched);
+
+ //End
+ QFinalState *final = new QFinalState(machine->rootState());
+
+ //### Add a nice animation when the torpedo is destroyed
+ launched->addTransition(this, SIGNAL(torpedoExplosed()),final);
+
+ //If the animation is finished, then we move to the final state
+ launched->addFinishedTransition(final);
+
+ //The machine has finished to be executed, then the boat is dead
+ connect(machine,SIGNAL(finished()),this, SIGNAL(torpedoExecutionFinished()));
+
+ machine->start();
+}
+
+void Torpedo::setCurrentSpeed(int speed)
+{
+ if (speed < 0) {
+ qWarning("Torpedo::setCurrentSpeed : The speed is invalid");
+ return;
+ }
+ currentSpeed = speed;
+}
+
+void Torpedo::onAnimationLaunchValueChanged(const QVariant &)
+{
+ foreach (QGraphicsItem *item , collidingItems(Qt::IntersectsItemBoundingRect)) {
+ if (item->type() == Boat::Type) {
+ Boat *b = static_cast<Boat *>(item);
+ b->destroy();
+ }
+ }
+}
+
+void Torpedo::destroy()
+{
+ launchAnimation->stop();
+ emit torpedoExplosed();
+}
diff --git a/examples/animation/sub-attaq/torpedo.h b/examples/animation/sub-attaq/torpedo.h
new file mode 100644
index 0000000..33bbc04
--- /dev/null
+++ b/examples/animation/sub-attaq/torpedo.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef __TORPEDO__H__
+#define __TORPEDO__H__
+
+//Qt
+#include <QObject>
+
+#if defined(QT_EXPERIMENTAL_SOLUTION)
+# include "qvariantanimation.h"
+# include "qgraphicswidget.h"
+#else
+# include <QVariantAnimation>
+# include <QtGui/QGraphicsWidget>
+#endif
+
+class PixmapItem;
+
+class Torpedo : public QGraphicsWidget
+{
+Q_OBJECT
+Q_PROPERTY(QPointF pos READ pos WRITE setPos)
+public:
+ Torpedo(QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0);
+ void launch();
+ void setCurrentSpeed(int speed);
+ void destroy();
+
+Q_SIGNALS:
+ void torpedoExplosed();
+ void torpedoExecutionFinished();
+
+private slots:
+ void onAnimationLaunchValueChanged(const QVariant &);
+
+private:
+ int currentSpeed;
+ PixmapItem *pixmapItem;
+ QVariantAnimation *launchAnimation;
+};
+
+#endif //__TORPEDO__H__
diff --git a/examples/declarative/animation/animation.qml b/examples/declarative/animation/animation.qml
new file mode 100644
index 0000000..1d60ac0
--- /dev/null
+++ b/examples/declarative/animation/animation.qml
@@ -0,0 +1,28 @@
+<Rect width="400" height="200" color="white">
+ <Rect width="40" height="40" y="80" color="#FF0000" radius="10">
+
+ <x>
+ <!--
+ Animate the x property. Setting repeat to true makes the
+ animation repeat indefinitely, otherwise it would only run once.
+ -->
+ <SequentialAnimation running="true" repeat="true">
+ <!-- Move from 0 to 360 in 500ms, using the easeInOutQuad easing function -->
+ <NumericAnimation from="0" to="360" easing="easeInOutQuad" duration="500"/>
+ <!-- Then pause for 200ms -->
+ <PauseAnimation duration="200"/>
+ <!-- Then move back to 0 in 2 seconds, using the easeInOutElastic easing function -->
+ <NumericAnimation from="360" to="0" easing="easeInOutElastic" duration="2000"/>
+ </SequentialAnimation>
+ </x>
+
+ <color>
+ <!-- Alternate color between red and green -->
+ <SequentialAnimation running="true" repeat="true">
+ <ColorAnimation from="#FF0000" to="#00FF00" duration="5000"/>
+ <ColorAnimation from="#00FF00" to="#FF0000" duration="5000"/>
+ </SequentialAnimation>
+ </color>
+
+ </Rect>
+</Rect>
diff --git a/examples/declarative/behaviours/MyRect.qml b/examples/declarative/behaviours/MyRect.qml
new file mode 100644
index 0000000..e40bd1b
--- /dev/null
+++ b/examples/declarative/behaviours/MyRect.qml
@@ -0,0 +1,4 @@
+<Rect radius="15" pen.color="black" width="100" height="100" id="Page">
+ <MouseRegion anchors.fill="{parent}" onClicked="bluerect.parent = Page; bluerect.x=0" />
+</Rect>
+
diff --git a/examples/declarative/behaviours/test.qml b/examples/declarative/behaviours/test.qml
new file mode 100644
index 0000000..a544028
--- /dev/null
+++ b/examples/declarative/behaviours/test.qml
@@ -0,0 +1,37 @@
+<Rect color="lightsteelblue" width="800" height="600" id="Page">
+ <MouseRegion anchors.fill="{parent}" onClicked="bluerect.parent = Page; bluerect.x = mouseX;" />
+
+ <MyRect color="green" x="200" y="200" />
+ <MyRect color="red" x="400" y="200" />
+ <MyRect color="yellow" x="400" y="400" />
+ <MyRect color="orange" x="400" y="500" />
+ <MyRect color="pink" x="400" y="0" />
+ <MyRect color="lightsteelblue" x="100" y="500" />
+ <MyRect color="black" x="0" y="200" />
+ <MyRect color="white" x="400" y="0" />
+
+ <Rect color="blue" x="0" y="0" width="100" height="100" id="bluerect">
+ <x>
+ <Behaviour>
+ <SequentialAnimation>
+ <NumericAnimation target="{bluerect}" properties="y" from="0" to="10" easing="easeOutBounce(amplitude:30)" duration="250" />
+ <NumericAnimation target="{bluerect}" properties="y" from="10" to="0" easing="easeOutBounce(amplitude:30)" duration="250" />
+ </SequentialAnimation>
+ <NumericAnimation target="{bluerect}" property="x" duration="500" />
+ </Behaviour>
+ </x>
+
+ <parent>
+ <Behaviour>
+ <SequentialAnimation>
+ <NumericAnimation target="{bluerect}" properties="opacity" to="0" duration="150" />
+ <SetPropertyAction target="{bluerect}" property="parent" />
+ <NumericAnimation target="{bluerect}" properties="opacity" to="1" duration="150"/>
+ </SequentialAnimation>
+ </Behaviour>
+ </parent>
+
+ </Rect>
+
+
+</Rect>
diff --git a/examples/declarative/connections/connections.qml b/examples/declarative/connections/connections.qml
new file mode 100644
index 0000000..3146338
--- /dev/null
+++ b/examples/declarative/connections/connections.qml
@@ -0,0 +1,9 @@
+<Rect id="rect" color="blue" width="40" height="30">
+ <Rect id="dot" color="red" width="3" height="3" x="{rect.width/2}" y="{rect.height/2}"/>
+ <MouseRegion id="mr" anchors.fill="{rect}"/>
+ <Connection sender="{mr}" signal="clicked(x,y)">
+ color="green";
+ dot.x = x-1;
+ dot.y = y-1;
+ </Connection>
+</Rect>
diff --git a/examples/declarative/contacts/contacts.pro b/examples/declarative/contacts/contacts.pro
new file mode 100644
index 0000000..18293ee
--- /dev/null
+++ b/examples/declarative/contacts/contacts.pro
@@ -0,0 +1,22 @@
+TEMPLATE = app
+TARGET = contacts
+
+MOC_DIR = .moc
+OBJECTS_DIR = .obj
+
+QT += declarative script sql
+
+unix {
+ sqlitedb.output = ${QMAKE_FILE_BASE}.sqlite
+ sqlitedb.commands = rm -f ${QMAKE_FILE_OUT}; if which sqlite3 ; then sqlite3 ${QMAKE_FILE_OUT} < ${QMAKE_FILE_NAME} ; fi
+ sqlitedb.input = SQL_SOURCES
+ sqlitedb.CONFIG += no_link target_predeps
+
+ QMAKE_EXTRA_COMPILERS += sqlitedb
+ QMAKE_EXTRA_TARGETS = sqlitedb
+}
+
+SQL_SOURCES += data/contacts.sql
+
+SOURCES += main.cpp
+
diff --git a/examples/declarative/contacts/contacts.qml b/examples/declarative/contacts/contacts.qml
new file mode 100644
index 0000000..d4647f9
--- /dev/null
+++ b/examples/declarative/contacts/contacts.qml
@@ -0,0 +1,44 @@
+<Rect id="page" width="320" height="480" color="white">
+ <resources>
+ <Component id="contactDelegate">
+ <Rect id="wrapper" x="20" width="{List.width-40}" color="#FEFFEE" pen.color="#FFBE4F" radius="5">
+ <filter><Shadow xOffset="5" yOffset="5" /></filter>
+ <MouseRegion id="pageMouse" anchors.fill="{parent}" onClicked="if (wrapper.state == 'Details') { wrapper.state = '';} else {wrapper.state = 'Details';}"/>
+ <Image id="portraitPic" src="{portrait}" x="10" y="10" />
+ <Text id="name" text="{firstName + ' ' + lastName}" anchors.left="{portraitPic.right}" anchors.leftMargin="10"
+ anchors.top="{portraitPic.top}" anchors.right="{wrapper.right}" anchors.rightMargin="10"
+ font.family="Comic Sans MS" font.bold="true" font.size="11"/>
+ <VerticalLayout id="email_layout" anchors.left="{name.left}" anchors.top="{name.bottom}" anchors.topMargin="10">
+ <Repeater id="email_list" dataSource="{emails}" >
+ <Component>
+ <Text text="{modelData}" height="18" font.italic="true" color="midnightblue" />
+ </Component>
+ </Repeater>
+ </VerticalLayout>
+ <height>{Math.max(email_layout.height + name.height + 25, portraitPic.height+20)}</height>
+
+ <states>
+ <State name="Details">
+ <SetProperty target="{wrapper}" property="color" value="white" />
+ <SetProperty target="{wrapper}" property="x" value="0" />
+ <SetProperty target="{wrapper}" property="height" value="{List.height}" />
+ <SetProperty target="{wrapper}" property="width" value="{List.width}" />
+ <SetProperty target="{wrapper.ListView.view}" property="yPosition" value="{wrapper.y}"/>
+ <SetProperty target="{wrapper.ListView.view}" property="locked" value="1"/>
+ </State>
+ </states>
+
+ <transitions>
+ <Transition>
+ <ParallelAnimation>
+ <ColorAnimation duration="500" />
+ <NumericAnimation duration="150" properties="x,yPosition,height,width"/>
+ </ParallelAnimation>
+ </Transition>
+ </transitions>
+ </Rect>
+ </Component>
+ </resources>
+
+ <ListView id="List" model="{contactModel}" width="320" height="480" clip="true" delegate="{contactDelegate}"/>
+</Rect>
diff --git a/examples/declarative/contacts/dummydata/contactModel.qml b/examples/declarative/contacts/dummydata/contactModel.qml
new file mode 100644
index 0000000..341b7a6
--- /dev/null
+++ b/examples/declarative/contacts/dummydata/contactModel.qml
@@ -0,0 +1,103 @@
+<ListModel>
+ <Contact>
+ <firstName>Aaron</firstName>
+ <lastName>Kennedy</lastName>
+ <portrait>contact.png</portrait>
+ <emails>
+ <Email address="akennedy@trolltech.com"/>
+ <Email address="aaron.kennedy@trolltech.com"/>
+ </emails>
+ </Contact>
+ <Contact>
+ <firstName>Contact</firstName>
+ <lastName>1</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Contact</firstName>
+ <lastName>2</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Contact</firstName>
+ <lastName>3</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Contact</firstName>
+ <lastName>4</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Contact</firstName>
+ <lastName>5</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Contact</firstName>
+ <lastName>6</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Contact</firstName>
+ <lastName>7</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Contact</firstName>
+ <lastName>8</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Contact</firstName>
+ <lastName>9</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Alan</firstName>
+ <lastName>Alpert</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Betty</firstName>
+ <lastName>Boo</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Foo</firstName>
+ <lastName>Bar</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Marius</firstName>
+ <lastName>Bugge Monsen</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Martin</firstName>
+ <lastName>Jones</lastName>
+ <portrait>contact.png</portrait>
+ <emails>
+ <Email address="mjones@trolltech.com"/>
+ <Email address="martin.jones@trolltech.com"/>
+ </emails>
+ </Contact>
+ <Contact>
+ <firstName>Michael</firstName>
+ <lastName>Brasser</lastName>
+ <portrait>contact.png</portrait>
+ <emails>
+ <Email address="mbrasser@trolltech.com"/>
+ </emails>
+ </Contact>
+ <Contact>
+ <firstName>Yann</firstName>
+ <lastName>Bodson</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+ <Contact>
+ <firstName>Yogi</firstName>
+ <lastName>Bear</lastName>
+ <portrait>contact.png</portrait>
+ </Contact>
+</ListModel>
diff --git a/examples/declarative/contacts/main.cpp b/examples/declarative/contacts/main.cpp
new file mode 100644
index 0000000..6bf9daf
--- /dev/null
+++ b/examples/declarative/contacts/main.cpp
@@ -0,0 +1,80 @@
+#include "qml.h"
+#include <qfxview.h>
+
+#include <QWidget>
+#include <QApplication>
+#include <QFile>
+#include <QTime>
+#include <QVBoxLayout>
+
+const char *defaultFileName("contacts.xml");
+
+class Contacts : public QWidget
+{
+Q_OBJECT
+public:
+ Contacts(const QString &fileName, int = 240, int = 320, QWidget *parent=0, Qt::WindowFlags flags=0);
+
+public slots:
+ void sceneResized(QSize size)
+ {
+ if(size.width() > 0 && size.height() > 0)
+ canvas->setFixedSize(size.width(), size.height());
+ }
+
+private:
+ QFxView *canvas;
+};
+
+Contacts::Contacts(const QString &fileName, int width, int height, QWidget *parent, Qt::WindowFlags flags)
+: QWidget(parent, flags), canvas(0)
+{
+ setAttribute(Qt::WA_OpaquePaintEvent);
+ setAttribute(Qt::WA_NoSystemBackground);
+
+ QVBoxLayout *vbox = new QVBoxLayout;
+ vbox->setMargin(0);
+ setLayout(vbox);
+
+ canvas = new QFxView(this);
+ QObject::connect(canvas, SIGNAL(sceneResized(QSize)), this, SLOT(sceneResized(QSize)));
+ canvas->setFixedSize(width, height);
+ vbox->addWidget(canvas);
+
+ QFile file(fileName);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setXml(xml, fileName);
+
+ canvas->execute();
+}
+
+int main(int argc, char ** argv)
+{
+ QApplication app(argc, argv);
+
+ bool frameless = false;
+
+ int width = 240;
+ int height = 320;
+
+ QString fileName;
+ for (int i = 1; i < argc; ++i) {
+ QString arg = argv[i];
+ if (arg == "-frameless") {
+ frameless = true;
+ } else {
+ fileName = arg;
+ break;
+ }
+ }
+ if (fileName.isEmpty())
+ fileName = QLatin1String(defaultFileName);
+
+ Contacts contacts(fileName, width, height, 0, frameless ? Qt::FramelessWindowHint : Qt::Widget);
+ contacts.show();
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/examples/declarative/declarative.pro b/examples/declarative/declarative.pro
new file mode 100644
index 0000000..3083800
--- /dev/null
+++ b/examples/declarative/declarative.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+CONFIG = ordered
+
+SUBDIRS += minehunt \
diff --git a/examples/declarative/dial/DialLibrary/Dial.qml b/examples/declarative/dial/DialLibrary/Dial.qml
new file mode 100644
index 0000000..acff119
--- /dev/null
+++ b/examples/declarative/dial/DialLibrary/Dial.qml
@@ -0,0 +1,13 @@
+<Item width="210" height="210">
+ <properties><Property name="value" type="real" value="0"/></properties>
+ <Image id="Background" src="background.svg"/>
+ <Item x="102" y="98" rotation="-130">
+ <rotation><Follow spring="1.4" damping=".15" source="{Math.min(Math.max(-130, value*2.2 - 130), 133)}"/></rotation>
+ <Image src="needle.svg" x="-102" y="-98"/>
+ </Item>
+ <Item x="104" y="102" rotation="-130">
+ <rotation><Follow spring="1.4" damping=".15" source="{Math.min(Math.max(-130, value*2.2 - 130), 133)}"/></rotation>
+ <Image src="needle_shadow.svg" x="-104" y="-102"/>
+ </Item>
+ <Image src="overlay.svg"/>
+</Item>
diff --git a/examples/declarative/dial/DialLibrary/background.svg b/examples/declarative/dial/DialLibrary/background.svg
new file mode 100644
index 0000000..415320d
--- /dev/null
+++ b/examples/declarative/dial/DialLibrary/background.svg
@@ -0,0 +1,385 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="210px" height="210px" viewBox="0 0 210 210" enable-background="new 0 0 210 210" xml:space="preserve">
+<defs>
+</defs>
+<radialGradient id="SVGID_1_" cx="0.8066" cy="-16.5908" r="92.0159" gradientTransform="matrix(0.9944 0 0 -0.9944 101.1987 90.0014)" gradientUnits="userSpaceOnUse">
+ <stop offset="0.1264" style="stop-color:#E0E0E0"/>
+ <stop offset="0.3421" style="stop-color:#C7C7C7"/>
+ <stop offset="0.5495" style="stop-color:#B3B3B3"/>
+ <stop offset="0.721" style="stop-color:#B1B1B1"/>
+ <stop offset="0.7828" style="stop-color:#AAAAAA"/>
+ <stop offset="0.8269" style="stop-color:#9E9E9E"/>
+ <stop offset="0.8625" style="stop-color:#8D8D8D"/>
+ <stop offset="0.893" style="stop-color:#777777"/>
+ <stop offset="0.92" style="stop-color:#5C5C5C"/>
+ <stop offset="0.9445" style="stop-color:#3C3C3C"/>
+ <stop offset="0.9662" style="stop-color:#171717"/>
+ <stop offset="0.978" style="stop-color:#000000"/>
+</radialGradient>
+<circle fill="url(#SVGID_1_)" cx="102" cy="98" r="85"/>
+<path opacity="0.5" fill="#FFFFFF" fill-opacity="0.8" enable-background="new " d="M57,169c0,0,20.146,5.732,45.001,5.732
+ C126.855,174.732,147,169,147,169s-20.145,12.846-44.999,12.846C77.146,181.846,57,169,57,169z"/>
+<image overflow="visible" opacity="0.75" enable-background="new " width="206" height="206" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAM8AAADPCAYAAABSgYVfAAAACXBIWXMAAAsSAAALEgHS3X78AAAA
+GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAIVhJREFUeNrsnQtz27oOhKGH7SRN
+m3P//588p83DdmzptjPiFNksQMqWHdkGZzRO0zbxg58WWIKgSIwYMWLEiHHOUcVbcDXvex9va8Bz
+re9rdaL3vz/iezECnlm9h1Xm++dQnt74uz6ACnjm8p5VBY+VA1V1Imj0Y+/8XQ66GM5o4y04CBgL
+jpr8HbtOCY91pb/vMnAFSAHPSYDxrjrzaEFUTQCOBUyXeczBFiAFPJMCUwMYpRcCdUwIx0ItBkjp
+1cPXAVLAMzkw6WrIo75q+JqBVE0IT+8Asx8u/TV+Tz92AVLAUwrNGGDS1TqPLYGpcVRoipyHqc2e
+XLvh2juP+wxIXUA0XcJ6DSpTZ4BpAZCF8diSf9uCSqH6HPo5YL6D4HQEFn29G487A6R9Jme6OYja
+G4OGOWO1EYIhDAtyLeHPDCSmPlbecyhAqDxMbRCUdG3hz+8EKK1MHkg3pUbtjULjhWMWLEvjQoha
+Ax78vTKh8oiT6zDF0dBsjQvB8lSpu8WQrr1ycHLQjIFlNVxL9bg01KdxwGFmwRR5T+/kPVo9UHXS
+tRmuLXncFoCE8F49QO2VQiNG4o8qkwOFXfrfpP/bAjgYquXWd0rv1lbJj7Xe0xmmQQIgAbEBgLxr
+C/AhSDcDUXvF0FSQyzCVYaDcGY+W4rDcBteD2MT3ymrGmB7ez8b1G5YLWQr051oPF36NyoSKxHKj
+qysDqq4IHGYzeyqjYbkfHvFCxVk40ORCst5RiDEAVWLb7FLw+3sjJ7IgWsP1BkBtILx7d0I6b80o
+4JlJiGZBo4FJ0OgrfS/9G602LDRjyT86YGPLYyyAStalrLIg7zl2JKR7Jyr0BgC9EZg2hhpZEF20
+ClUXDg4L0Sxo7gCah+FCgLTaoINWk3AMJ2IvfNXeWngcM5nYzcKrgEALvnKAR5AYRAgPu5gaMSW6
+eBWqLvg5W9C0kJcwYB4IPHeQ3+iwTE84Ic4WS8rZ1wygzgjpSnO6kkqIxjEzcMFWvy4W0jGAXtWl
+v+9BdPEq1F6J2mgjYElCMw3Lt+FCcFaQzzRkUllJN1uI3El+bYTlAjm3bUwJEVvoZd/HvE3/jA5C
+unuiQgmcF/W4HP5uMfy7ZgCodlToogBqLxScGhy0FF4xaDQsDBwdorWgMgyYd2L1vkOy/G5AxODJ
+FV968FhWvFUd0crnRV3Paq/U9/DGpCHSYe+L+gwSTBrajXp/Kng/LsqNay8EGjEMAQ1N+lBRZR4B
+mgeiNlppBICx3ChvZT5X3tIVOFB9oWFgLf6yOjyvUsJzExFMlkeWOJWvw8/YqOfLbioXAVF7QWpT
+EUMgfej6zqeBeVRfa3BKoMGE2VpEZPAcWhdWAo84LltTAJC3ILwkjwtQ5VJThi0sL4jCpffMs/UD
+niPDNPzQ9IelQ7JHuNL3MURrVHiGcb1OjjdiLxRuiOKw8pVO7DqwMQuIpVXhjeRLkBg81gKxlQ+2
+mSUBD552eC9rR4VmrUDtTKHxwjRUGx2efR8uVJx7Ak2llAZVZk3WMdYAz9YBxyrn70au7ZQ6jtYC
+sVeStCAKdEcsffweQlSr97U1fq5VC8jWzC4mF2pnrDbopuncBkM0Dc13Bc49fOAamp1K+reZNYwc
+OCWFkmOabxwCkMi4vUltAUD3wheS79T/0SbLgrifDNSF8CqN9fDcLyKMa2cMDiaoS/WBplDsO1yP
+AA6qTa/Cs61hueIjq+kaC01OaY6Bp1SJSiFaOVb/PRgud8Sp1Iux+LPZHqgFWU/Ta0/pfZW5KVA7
+Q3BqeOMX4KSh2vwAcB7Uh9pCXpNymg1Zo2CLfQycXE5TstOyP9F7mHPlqoKciAH0qgB6I0Ch3V+p
+mxYzeRaO+uCGwXf1+c0qhGtnDs6SrNl8J+B8V/lNiq/TB9GpvGYr9sIeA8daId/J+IYZ5wg7qoyx
+kLO3sUJDQ/QKywDpPXpQNyx900rv/9JYk1tkch/s8bBTEM0CoGaGjppWmwTNo4Ll6ff1z3A9Ddd3
+CNVS6JDUJhU2/gHl1+/r5+/rP3L9+f7zcL0MFwNp54D0lXv8WdW2/rPXlsrarsB2oVpbEHROx5xS
+qzFKI35jlF5mWErWzAycloRpCRwNTbqS8qQ730K9pr1SmgTNLwOa9HcJHFSfXJVwJ/NthmEZFB5Q
+pSDhTQQBEvFLiNj29GqO+c2c4MmBo520H4XgpPxmr/KatwEGT20SOC/ysbCRQdOJvcnrUmqycv2s
+c9u4cx13GEDWlpGmIFybLUjNDMHRisPAeRq+/zhAtgS1eVch2jNA8y8J0XTOsybGgKUycmHQ5ICy
+2vXmQLKKX3vIT3IAsQrvWVvVzYWA8z/Ibx7VWkOjEsqtMgG02iA0vwAcndMwaG6lP1muE6l2FhEW
+1o0U37dcB1ZsyyVODndT8DC3Z1EIzj9gDKT8pgZT4FWpzU/HEGDQbIVXB9xiUz+voYjXlZQB1RtG
+QpUBqCoEqL8VePR+kdZw1XKOGoKDpsB/JEz7mTEDMGa/6U6YhaFdrid2NyIHYpcQiLwF57N/Vs0Z
+wfFCtW+ZHAfBqcBNe86Eac9gCLC8JqAZH85hQ5FO7E1/uRCutL/d1JUaB4/2zODotZylfKwa0Os4
+T8oYSI7aSj3fBI520zQ82nrWwGyEr08ENOXgVAUh3E7KdtOmn71UN9UxhoblGnbn+BzbM4HDVEfX
+qeEC6BOxorWjhjb0fwocFqJ5DlpAcxxEnjPn5UMIwkrNj6owB2PrVWdTo+YM8OCWaW8BFM0BvYZT
+KXBeHRs6uWnaFNgSeK6qh9jM8iGmTNZ77YVvrOLAaud1djOhPTE4WCGN4dojhGo/5O8azoO6G4nh
+qDFonuVjNbQO09haTYBzvCNnTe7cKXW9My+b4fP3fmafya2qU37G7YnBwY1srDr6hwIIwWkJOJYx
+kNTmRTlpqTpgX3AHjHFcKNcZYZQFUq7xic6BmNrkjInu1PlPc0JwKrEXQb8rtfFcNYFQDcH5V/6u
+6TwDOFsAJ8K0rw3jvJ4NuV50nmV9TBPJ2SoPGgRL+bz784e6Ejjoqlmhmg7X0IZGCzrCtK8L44S4
+YSL55o4CJsJK7F7be0OJROxzg2anPMxZY5Y0qk4K1/QCKNrRFjjaVdP7bvYRps1OgaTQPKgkfwiy
+l/ecJdJoTgBOJZ+b5N0b4GhLOhV56sqBMeAwxQlw5guTFLpvzIETACjXD/wkc2BqeKydoNpZY2U3
+D/J3oUyX3Oh1HA1NgHMdEAlxxgRA8bYrWEWrZynqbSYEp8qA81142Q0ugu4UONY6zkuAc1UA5cwD
+7wwkq+G+ZyLMBh7PXcMKAtyTk5w1tKStLQWhONetQF7Y5p3q4J1YcbLwbSp4WLh2T8I1XbeWNrOh
+QfCaAedFmQMBznU5dd55sta2Be/8VQ+e/qvhyblrrP/AkzIIkhWZdoAmS9orucGtBAHOdYBTGrox
+8+BQgL4cnlzBJ3PXMM/RW6d/OuBEqHY7w2sa0gjvdbAfCVD/VfAw1cn1INC9B7DY02oLpcFZh+Lc
+ZOjmta3SEFnbI7zdwWeHp9QkwHAt1a2hLc3Wc9BZS0We7wHO1Y4qYxzoUxnYoco6dMNGJZOHb8fC
+oztN4q7QJ8NdS3lOarbObGl01tbi16rFuC6A2A2anTtknRd7FoCaI8DRWw1SJUEqwcEdoUl1cBu1
+DtcsZ20NzlonJ/LtY8wGnpxhgOep6vANbWvvTNgvg4dtNWC9CHArdVKdFK6xPOcZDIKtAicU57oV
+Rwoct9YAqBJeOGqdZnHUXGqOuCvg+ZTaJPgh+cXQdUZ1MFzLbaCKcR3gVAXGAZ7sjdUHCaAEC7ZK
+3k0Rvh0KD+4M1QuiT4bqYLuoV/ncKopVSb+H6tx8+Gad6GABlHIfr9f2/ivgwd2haV0HF0Rxcxuu
+6TCToHQ9J8bt5T6V2GcKIUAC6oMnPLAjYkbPreaAF4MntqHDpvsRPILq4K7QUnctFCfCOA8eBKgi
+rlvp0Sgng0f77bhXhzXy0DtD+4zq4DZqDNdi3LZxYJkGCA/mPgyekt59k8HDDqBaGg4bU51kTVtt
+cXWrKKxbC9UJmLBVs3W6N3PeEB7vBIxRc6w+UHkaoj54YnJSnHRCmz7WEI8w1DlOLITGYK1809zY
+qDmj55Eu3Uqb63RqoednOnpzYZgNJ4GHOW0reHL6hGQ8N2dNXjhrhbuPcC2GkbdsFEB4A16rm2+a
+34vMHMVSn2pKeHIH7uKx4+ncnFZJ585RnXWoTowD1GedUZ8O8vM7mKeoPtihtJoCHhG73/SSPKGV
+cte06jC5XYtftxYjBgNoq+aOpT6dyusXBCCmPsXgTAGPPmp8pWhOJKeEjR3hrrcYxDaDGKXqs1Nz
+xptTSX0qkp9reJby2eaeBJ4xIZs2CTDX2ao7w5vww6WO8txj3ETugwBh+IZpQCcfW6FZN/uF8C3e
+1VQ5DwvZVuRJtGATviuJfRP/DNBQnRil6qPNgzW5KesFdlybROU5KHSbAp47yHUaYhRs4MWtw12L
+MaH7tiYAMdu6VH2OhscK2TzlacEo2MGLW4t9XHuoToxD1GdL5lhSpDS30lzPRUyjQrfSnMcL2ZaQ
+dNUQsuGL24jf/SZGjFLnTUc2CNCWhG7NCICOznmsc3bwl6fyCF3RunfuCngCdRz/EWOM+uB2A+8G
+vVehW+Pc/CeDx9rFp5UHLwzZLNXxwrUYMQ5RHzbXcC+YgHGwPDZ0K8l5EBxN7pIkWyxk03cCrTon
+7SUc46rBwf06W2O+eaHbEuAZpT7H5DxLMAq0y8bi0a2hOuGyxTjUdWPqszXyah26tYYAnCRss0I2
+TWv6WZ1xJ2CqE+DEmAKgXcGcw9BtYcxnBlBx2GY1226MX9pCyNaRO0FOdSJki3GIceCpz1Z4Dwzc
+UmOFbKg+1RjlkUzOg1tfRZkF7IW8G6oT0MQ4Nv/BXgXWDTsN3Inq5TxyqGHAtr4u4NK/iBXvpRfA
+du/FIbsxDgVHhPdoeycA6WgHd0SznajWMY7FylNLWdOFRj422mbKw7qWRLgWY8rwzYIH553I5x7r
+C7GbKNaH5jwlvbK0y6Ztaq/dT0AT4xThm9UpB7swYRcoq4VVPSbnqQoBQnAqyHd2wruUTNYnOEYM
+sY9U9OagNsNKel+LBdAY5fF+kRjOxy7jsEW+E2OKvKcfOf8kIwgHKY8AmaxHcEsSK1Ehm9XiNOzp
+GKfOe7rM/NurOVcyrw8qz/F6BFtH22G5RIRrMeYSvmE5mAg/dQ7DtlomqG3TJxFbbXqsM1F26vsB
+T4xzmAad+AdbiQGQdeK2lMBTid1guzbiQXTa9sIPFYpcJ8a5ch9rDqLj5s3t2mDhIOVhF4Zs7CTi
+Tuxu9AFQjKnBKZmLPTHFMIRz13hKDYPKAaeCF4JPmoVrAU6MUwDE0odO/H7UbH7r70lpzsMsuYr8
+QEZkTxTGO/skwIlxipyHuW/WfBSiPpXYLtsnPkr28wgBR0i+0ztPNOzpGHMACOcgi7AqI98pMgxQ
+qtgPqZwn3hU86RgxzgVQn1GdHDiMj1HKY30v9ySjsUeMOUHE8m3LYfYYKILHC+PGPGF0RWLEmAM4
+HjyVEYmNgqeke2J/wJOOEeMU0MhIcEpTk6OVJweORKgWYwYQWUDlUpPKyf0nh6c3/hzWdIxLGJZB
+djblYeBI5DgxZg5NNTKnPyk8MWJcu0IFPDFiHJmeBDwxbhqGPpOzf3nYVny+Y4wYMwGpGKB6AjhY
+shXAxLjk8KwIoKmUx7P8JGCKMdP8pWRRvz8lPBYsRScKx4hxglRBMjdzL3QrXl6pC0ntC57wwQV2
+MWJMnF+XzMOcwmRrMscqD/6i3BMuKrCLEeMEEJXc0BlAxdUxdSEsue9521kjfIsxJ4BYFJQrai6C
+p3ckq7Ss2+t3EADF+ApoWNMacVSnd1gYrTzYmUT/0BJwAqAYXwFOnYmGcCPnqG00tRP/Cfmh2JNA
+P/Fci6owD2J8JTiW+rCWVWyOf+KjdhSntC8BA4h1YBy92ShGjEJwUBCsDrcMnJK+G6Nr28a08LFO
+VGgyKhQAxZgCHNbEw5uLrFlniUBkDQOv+4jVtB3PO9Gd51nX+QAnxikBsuZgQ/Kd3Nw2FWiM8rAO
+jL0hl/pJt0b4FiPG1DmPnmctmYs1yfOtDrejlccL2VLj7L0BUKWetHXeScAT49TwWOfutEbIhocT
+7EtDtxLDwDrvRAMkMv6cx4AoxpQu25jzc6VwXo82DHqSTO2dX9QZYdsCHpswDWKcONcpnX8in8+S
+YlFVJ86aj1dhwABiv0iTidQvInyL8YXhGpuDOrLyBKGTTPHoGOXJnfOoHbcFPHmkP8CJcSqzgM27
+BXHaxpyfW6Q86EL0huroI7rZIanpCS+HywMoIIoxRb6D4Oi5hye39/Lx1Ox3Q31YpUEWHivn0b8s
+XfoX6RexdODBM00DoBiH5jsYriE8S4BHCwLO5Z34h2EVK48Q5Um/ZEtkTiDvWRCAtGUY4VuMKfOd
+NjPvGvV/MVzbEoDckK0k52F5jwZoC79Mr/Xgi1hmnLeAKMYh4Vrt3LD1nEtzTc/lrQNO9vzcMes8
+O4AGf6m2rHXYthouLaGoPjFiHAIRqo4357RFzURgayjPQYWhUgDQBtSnV45ba7wQS31ixDgEHKY6
+es61ymnrQXU2BeDI2JzHA+fd+MU6dGvUi1ll1KeK/CfGAXlOlVGdlbpZNxCyMQF4HwtQadjGlGcD
+ALHQLQF0N1wrQ30CnBiHAISqs1JzDfMdHbJtyRz2cp6ThW0bUB8duuk7AQLUgqSGcRCj1CjQqUFL
+wNHKgyGbdfOfNGzLwbMx4GGh253xwkJ9YhyrOuwGfVcQsm0yyjNJzlMSuuknkEK39OLYC8uFbwFR
+DEt1cuGavkHr9Z1uBDjZkK1EeZj64BNYq6/Tk0ihW6uU53649Atk8MSIkXPZNDwaHD3HUmSTQrZ0
+02fzFiOnopa7h8CDyrNWT0QbBzp0W5EXt3IACvWJUaI6K2duYci2c+bs6JBtTM6DoVtOfZJxUBN4
+HuBFYu4TChTDUhyW61jzaiF/a9n2I1SnKGQrVR4Nka4JQorfQH0SPBi6PcALXTrmQUAU0FgmQW5O
+tQoePV/fjGhJL/RPejKcFbppeNKlSRalPlpa04tlzkg4bzE8hw0dXA1Ogmeh5raOlHCubg4N2Q7J
+eXr5WBvEaF5D7oPq80DuFElmF6E+MRzVWRhpgL4Za9XRuc7aiJJ0bWY/tWGgIWJ7ezbqCb0B0dq2
+ttTnPmMexIhch5kE947qoD3tzVHW9KNoHHI+j+W6vakLc58qoz73oT4xRqjOfUZ1Ksh11sb8tPbv
+FI3myBflbX9leylE/L4IxW1/YtwEOKg4f4D59vv6/vt6Gq5/fl8/fl+Pw98vhv+7HyB5+X39+n39
+HK5fw/UygKQX90flPM3IF8Wsw5JdfLo4z+qLkIMnILqtUI0VF38bIHmC6/ugPqthTvcDFH/geFbg
+pOsPOK8kdDup8pSqj9U1JweQ1y84xm05awjOwwDOdwDnxwDV3fB/ZJhL6wGSBMx/Snle5LMz3I2d
+a4eEbVZM2hIFWhh5jA7frKZzB72gGFcBTu2Eaz8AnscBrKVy2JLq/AJ4finVSfDom/Wo0Uz4Yq2G
+cxi6seMdvH7BEbrdXp6j13Puler8UHnOPwNMTHXeHNV5hVyHNe88adiWC9+wVzCzoHXVAjvmwetW
+HxBdb57TFIRr2iRA1dkMgPwi4DwT1dkfojrH5jw59cGuodbeHdatfu+YBwHO9YZruH2fuWvaJPgm
+fze89YOSJJPg1wBOup4d1ZFzwVNiHrDjHdoCgKyDhsI8uK08Z6nAeQTF0aqTwrUKTAINTgrdnuXj
+Gs/ReXVz5IvO5T+NA1Aj/GDVzgjdOgjZAqLry3N0wec3I8/5MajOPTEJXgdIGDgpXNsog6o75gU0
+J7qD5FQIzyoVyZ+Bin2DA57rAAc74HgGgV7TuYNwbQ3hml4UTQuia/m8rnNwNNNM/EZgWyBLgfC4
+ETHCt9EnFMe4OHDQIEjh2g8I1/Sazr18XtN5BXftP6I62OH2qHk0Rc6Ty4G0C9eQr9kWhA5A6iP3
+uVpwWgLOd1CdJ3DXFiRcS+7av/J5QTTlOlhBfdSYMmxjKsQUiB2y2hADAbdC9BG6XS04yVl7BHD+
+B+Gadtc6cNd+grv2S5kEk4ZrU4dtJepTy+djvb3T4qwj7XtQpxiXC06qIHjI5DkpXEsdcXrHXbPC
+NSzDOXo0J36jcgqklccDyIIpwrfLB+fecNaeIFxLe3VE/lZMvxrgsKrp3dRhf3OCN8r6Gh242gAJ
+9/BUJETrCFQxLhOcpDi4lvMPAQerCJ4dcFLV9HbqcO0U8FQjFKg2AKpBgWr4eb0BTQB02eBoxfmf
+Upy0nrNS4KQ854U4a2cJ104ZtpWYCZYK1eTydpOyotGA6DLMASvH0QuhD8QgWBNwdJ7juWuT3mSb
+MwCjRy22ld0YAFlhnBBY+sLnFeP8arNU5sA3xxzQ2wz05radfNwZmqD5Vz4WfrISnJPkx80Jwcnl
+Q7XYVQm1EcYxFaqMN6YPcL4EHLa+hz3WWI7zBIqzUvPTAseypU8arp0zbCsN4UovL4yr4I0KYL4+
+TNPgPIpvR3vg4DYDBOf11O7aV8FTFbzhHkxeOCcGTAkkL+QLuKaHRne6SbVqVuUALoImcFoCzrOh
+OKyK4Cw7kc9tGFj5UOWEcrk8yAvpcvDGmD5MW4DiPBjgsLIbDc4ewPmpchy9R+flnHnOOeGpjoSt
+zuRHtfBzTRlQhwAWw1cbrIpmG9lSmIYLoP84odpe/hZ7ojnAFkKtos+TjuYLP4B+RDhQAo4FUlUY
+4gVE40I0q2ffnfCqAaxVG5vjeOC8C++C018jPJ4rZt3d6hH5UClMng0eEPnQNIbaPBjgsFAtbWgr
+NQewgoA5a2fruPQVbpu1LuO94NIqhdziqwZJxLa+A6L89pKWqI3VrMOqVWPrOMwc0KqDu0Inr5ae
+IzxscbMi8PRODlRJWaUCg4kZDrk1JHGculvJaSpDbfSpbFptvou/hpNaRelatV2BOWBtbNvJF/X3
+a2bygfUGQFbPNm+BFfcNWdsfWM5UYjBUNwBN7YRoK/l4UoGGJhempW0FGpx0isGLYw54ivNlmySb
+GX14ua0HJXfHUoCsau4xRsM1nN5QjYBmKZ+P97DAQTftm/ytU0tWNNaqeeaAF6p92e7iZmYfpgeQ
+lxd5CW2uDVYuNypRoeoKoGkMF806wpD1jbYqBtLpBSm/SWs4b2KX3DBzYDbgzBEeC5wuo0al/eMW
+BkAeSFauZDl1c1SknPWvX/cClEYfSKaVhjUi1GqT3LTUW43lN6w6WlcPMFdtFuDMFR5PgTrja2uS
+lAJUqkhepUMOpuoLVcWDhjXoT9CgGWCFaLqL56MyBbQNrcM0NAZYrZpex9G91mZzflM7E0jSmytG
+mMaawePBWOm6k4+HaqXktHXuqK9w6Q8tlX1s5fOJDrnWWD1xF/sTgyNGbuatmyFES8hx2PmfDyqX
+0Yczr9QNSJ/QlsDRodovleskaHR+g4ozqw5K7YxURgO0g79nrXjTB4LXTj4eEoyNR9jdNU0MBhBC
+9G5ApO+InZOzyYk+9Cpj7dckv/GUh70/+ihM70zZCtRmoxQHwdHQsPxmluDMBR4GUA/g9AY8CBDG
+xSuiQg25u94PsCBEFkAWRCVqZBkf/QGgMOevRGUsaHLg3MvHU8zvyHtcyccT07UxkCBh0GCd2hbe
+19k1fZkLPGzy7Em+g+eZvhvwpDf/gahQI/zksTsF0YN8PAB2DRBtD4SoI7ncsfBgTlUfCA2qsQ5r
+9XWn8pklQJOcNKY2LwoYDNGsMG3Wp2TMCR4MayrDhfPUBye1lv0VfNit8HavadKsVYy+LgDoXT4f
+TFwS0o0N57zwzArNcM1mUQDOHcCiocEjY3qlNvp09FelOBoYHaK9kTCNHa8pMrP+FHODxwrhmAKx
+3EdPaAyz7kmYUYFdrSHaqLsne2Rh3HtBTmQZC2OVp7QzESrNwgjTVur9wccVgUbnNTtQmzflqD0T
+aF7gprSVCzwRfY7weBCx5u87R4E2cOkEd6lyoAoUCQseN+rnbQ14MIzTk8EyFqaEh0HDDhpbEsXR
+gODjAnIafarFXr3fWm1eARYNzSvJbS4iTLskeErCuJwCbUBB1mCtrsjESDBhOMdyqq0BTw6g7giA
+ctazBw6DR18LUBh2kvneUBvtVCIwL5DbbBy1uZhe5HOHxwvjuoyFbcGjIbpzQhJtLOwVRBqKreH0
+sfDNmiR9gYFQum5jnYe0IOqjYcJzY/XhY9oIYO8vA+eFKM2b+izeidpc3AkYlwBPSS5kmQhbAOfP
+B/hNfZhoubJkWOdF1u/yFm13honQZcyDnFmQ63/XGhDlKiqwV7gHzRpCtRd4fCMmSy63uZimlZcE
+DwvjLBsbP2wdk7/BuoVlweqJxmxfZl7sIUTbZ8DpRtjWlvrUGYBKtmcwYDpyI9oCNG8Azyt836rQ
+sHZ9XlS310uDh73BneHGoYnA7pbWGsaKJMzWfqB++Hs9GZjDVgLOWKvaA4g5bxXkLwyYvTICMPxl
+4LyRNTEPmqs54fwa9qOI5PfYLwxb9l4+Lgbq9Y2VAZF1LCSe5sCKWI9d6yld42HdhKzn6JkuOmd8
+I/CsCTAbYpzsr0VtrgkeK4m2EmirDAVhujNUaGm4UdbxKKiY3o5ZGQGPBZAU/P5cjrg11GZNYMmV
+LeUMkqu4c18LQFKw9sHUiNV0rQhAJRBheFTSoH7sHTjX+RRrAztI/kug2UCyz2r8mMrk1rREruQk
+i2vcj2+Fcl75vRXaWVf6dzmrlylSKUxjPjdv/xMzM9BqZ4u/1oX2fOk2jauB5prhERK+jCmUZDVf
+TKFQgTAnasU+tGvqzXF9gfPIimmtciZ83BoKkyuEFbnig8euvZ0SS7BrsRuGWCB5K/MLYihYayi1
+YTJUBwLDkn9r6wYrYfKqJd4LgMF8ppMbOmzslnqRScahKqkLw4upzsKAhzUYOfYzQGePrTuxBVy2
+jYNtKiypzxuzVhXwXKGxUFrO3xKgco1FWvEbL06hPCxc60Apdg5IuwJ1GbNT9ubuyLcMEYZ0pSv3
+7NHqE2f1z54i3+mcfIep0N55zFVC3FRoFvAcFtKVrOAzhbL6Z+dMg2okMDmzACFiQHXCqyFK9x31
+MXFiHALS2CMhq0y+cww8IryKofTqA5iA59wglZTHlPZ3O8YwsCZ8J2XlQQFMwHNWkNjXtfinOpyi
+abwVwlkJvbUGE8AEPGcHKfeYO4t1anhE/FMmvGQ/gAl4vvQ9LDl5+xTvuwdBn/l+jIBn1u/rqQ4R
+7o/4XoyAJ973gCNGjBgxYsS49vF/AQYAwYoCo3RnAfgAAAAASUVORK5CYII=">
+</image>
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-15.9541" y1="83.9062" x2="13.6193" y2="-106.171" gradientTransform="matrix(1 0 0 -1 102.5 88)">
+ <stop offset="0" style="stop-color:#B3B3B3"/>
+ <stop offset="0.151" style="stop-color:#AFAFAF"/>
+ <stop offset="0.301" style="stop-color:#A3A3A3"/>
+ <stop offset="0.4506" style="stop-color:#8F8F8F"/>
+ <stop offset="0.6001" style="stop-color:#737373"/>
+ <stop offset="0.7495" style="stop-color:#4F4F4F"/>
+ <stop offset="0.8968" style="stop-color:#232323"/>
+ <stop offset="1" style="stop-color:#000000"/>
+</linearGradient>
+<path fill="url(#SVGID_2_)" d="M101,187.999c-50.178,0-91-40.821-91-91c0-50.178,40.822-91,91-91c50.178,0,91,40.822,91,91
+ C191.999,147.178,151.178,187.999,101,187.999L101,187.999z M101,13c-46.316,0-84,37.684-84,84c0,46.316,37.684,84,84,84
+ c46.316,0,84-37.684,84-84C185,50.683,147.316,13,101,13L101,13z"/>
+<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-79.4551" y1="-54.0073" x2="76.4557" y2="36.0078" gradientTransform="matrix(1 0 0 -1 102.5 88)">
+ <stop offset="0" style="stop-color:#ECECEC"/>
+ <stop offset="0.0105" style="stop-color:#DDDDDD"/>
+ <stop offset="0.0399" style="stop-color:#B7B7B7"/>
+ <stop offset="0.0704" style="stop-color:#979797"/>
+ <stop offset="0.1021" style="stop-color:#7F7F7F"/>
+ <stop offset="0.1353" style="stop-color:#6E6E6E"/>
+ <stop offset="0.1712" style="stop-color:#636363"/>
+ <stop offset="0.2143" style="stop-color:#606060"/>
+ <stop offset="0.4615" style="stop-color:#FFFFFF"/>
+ <stop offset="0.5195" style="stop-color:#CFCFCF"/>
+ <stop offset="0.5899" style="stop-color:#9A9A9A"/>
+ <stop offset="0.6512" style="stop-color:#747474"/>
+ <stop offset="0.7002" style="stop-color:#5D5D5D"/>
+ <stop offset="0.7308" style="stop-color:#545454"/>
+ <stop offset="1" style="stop-color:#ECECEC"/>
+</linearGradient>
+<path fill="url(#SVGID_3_)" d="M101,7C51.294,7,11,47.294,11,97s40.294,90,90,90c49.705,0,90-40.294,90-90S150.705,7,101,7z
+ M101,182c-46.945,0-85-38.057-85-85c0-46.944,38.055-85,85-85c46.943,0,85,38.056,85,85C186,143.943,147.943,182,101,182z"/>
+<circle fill="none" cx="102" cy="98.001" r="65"/>
+<text transform="matrix(-0.6383 -0.7436 0.7588 -0.6513 54.624 142.6035)" font-family="'MyriadPro-Regular'" font-size="12">0</text>
+<text transform="matrix(-0.589 -0.7833 0.7993 -0.601 50.7637 138.0234)" font-family="'MyriadPro-Regular'" font-size="12.0005"> </text>
+<text transform="matrix(-0.3613 -0.911 0.9296 -0.3686 42.665 124.7539)" font-family="'MyriadPro-Regular'" font-size="12">1</text>
+<text transform="matrix(-0.275 -0.9406 0.9598 -0.2807 40.4512 119.1719)" font-family="'MyriadPro-Regular'" font-size="12">0</text>
+<text transform="matrix(-0.213 -0.9566 0.9761 -0.2173 38.8223 113.4023)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(0.0159 -0.9799 0.9999 0.0162 36.96 100.019)" font-family="'MyriadPro-Regular'" font-size="12.0004">2</text>
+<text transform="matrix(0.104 -0.9745 0.9944 0.1061 37.0518 94.0215)" font-family="'MyriadPro-Regular'" font-size="12.0005">0</text>
+<text transform="matrix(0.167 -0.9657 0.9854 0.1704 37.7407 88.0718)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(0.3752 -0.9053 0.9238 0.3828 40.7725 75.9199)" font-family="'MyriadPro-Regular'" font-size="12">3</text>
+<text transform="matrix(0.4573 -0.8669 0.8845 0.4666 43.0674 70.3799)" font-family="'MyriadPro-Regular'" font-size="11.9993">0</text>
+<text transform="matrix(0.5127 -0.8352 0.8523 0.5231 45.9121 65.1069)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(0.6672 -0.7178 0.7325 0.6808 52.3262 55.9673)" font-family="'MyriadPro-Regular'" font-size="12">4</text>
+<text transform="matrix(0.7301 -0.6537 0.6671 0.745 56.4102 51.5703)" font-family="'MyriadPro-Regular'" font-size="12">0</text>
+<text transform="matrix(0.7708 -0.6052 0.6176 0.7865 60.9082 47.6182)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(0.8905 -0.4092 0.4175 0.9087 72.1504 40.165)" font-family="'MyriadPro-Regular'" font-size="12">5</text>
+<text transform="matrix(0.9246 -0.3249 0.3315 0.9435 77.6006 37.6587)" font-family="'MyriadPro-Regular'" font-size="12.0005">0</text>
+<text transform="matrix(0.944 -0.2633 0.2687 0.9632 83.2959 35.7197)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(0.9797 -0.0248 0.0253 0.9997 97.3081 33.0972)" font-family="'MyriadPro-Regular'" font-size="12">6</text>
+<text transform="matrix(0.9779 0.0643 -0.0656 0.9978 103.3198 32.9438)" font-family="'MyriadPro-Regular'" font-size="11.9994">0</text>
+<text transform="matrix(0.9717 0.1274 -0.13 0.9915 109.2959 33.3921)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(0.9148 0.3514 -0.3586 0.9335 122.4863 36.2207)" font-family="'MyriadPro-Regular'" font-size="12">7</text>
+<text transform="matrix(0.8783 0.4348 -0.4437 0.8962 128.0967 38.375)" font-family="'MyriadPro-Regular'" font-size="12">0</text>
+<text transform="matrix(0.8481 0.4911 -0.5011 0.8654 133.4463 41.085)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(0.719 0.6659 -0.6795 0.7337 143.9395 48.2495)" font-family="'MyriadPro-Regular'" font-size="12">8</text>
+<text transform="matrix(0.6551 0.7289 -0.7438 0.6684 148.3438 52.3242)" font-family="'MyriadPro-Regular'" font-size="12">0</text>
+<text transform="matrix(0.6067 0.7696 -0.7853 0.6191 152.3047 56.814)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(0.4267 0.8822 -0.9002 0.4354 159.2344 67.0146)" font-family="'MyriadPro-Regular'" font-size="11.9996">9</text>
+<text transform="matrix(0.3433 0.9179 -0.9366 0.3503 161.8438 72.4062)" font-family="'MyriadPro-Regular'" font-size="11.9996">0</text>
+<text transform="matrix(0.2823 0.9384 -0.9576 0.2881 163.8945 78.0513)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(0.1113 0.9737 -0.9935 0.1136 166.2334 87.54)" font-family="'MyriadPro-Regular'" font-size="12">1</text>
+<text transform="matrix(0.0217 0.9798 -0.9998 0.0221 166.917 93.5156)" font-family="'MyriadPro-Regular'" font-size="12.0005">0</text>
+<text transform="matrix(-0.067 0.9777 -0.9977 -0.0684 167.0527 99.502)" font-family="'MyriadPro-Regular'" font-size="12.0005">0</text>
+<text transform="matrix(-0.1305 0.9713 -0.9911 -0.1331 166.5859 105.5)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(-0.2564 0.9459 -0.9652 -0.2616 165.5303 112.1348)" font-family="'MyriadPro-Regular'" font-size="12">1</text>
+<text transform="matrix(-0.3429 0.918 -0.9368 -0.3499 163.9658 117.918)" font-family="'MyriadPro-Regular'" font-size="12">1</text>
+<text transform="matrix(-0.4267 0.8822 -0.9002 -0.4354 161.8613 123.5527)" font-family="'MyriadPro-Regular'" font-size="11.9996">0</text>
+<text transform="matrix(-0.4834 0.8525 -0.8699 -0.4932 159.1973 128.9287)" font-family="'MyriadPro-Regular'" font-size="12"> </text>
+<text transform="matrix(-0.5948 0.7788 -0.7947 -0.607 155.5195 135.0195)" font-family="'MyriadPro-Regular'" font-size="12">1</text>
+<text transform="matrix(-0.6637 0.721 -0.7357 -0.6773 151.8789 139.791)" font-family="'MyriadPro-Regular'" font-size="12">2</text>
+<text transform="matrix(-0.7269 0.6572 -0.6707 -0.7418 147.8154 144.2051)" font-family="'MyriadPro-Regular'" font-size="12.0006">0</text>
+<path fill="#333333" d="M141.121,133.456l7.08,6.485l-0.436,0.475l-7.08-6.484L141.121,133.456z"/>
+<path fill="#333333" d="M143.077,132.336l4.927,4.186l-0.541,0.637l-4.926-4.186L143.077,132.336z"/>
+<path fill="#333333" d="M144.354,130.73l5.092,4l-0.518,0.658l-5.091-4L144.354,130.73z"/>
+<path fill="#333333" d="M145.572,129.104l5.234,3.806l-0.492,0.676l-5.233-3.806L145.572,129.104z"/>
+<path fill="#333333" d="M146.73,127.412l5.379,3.6l-0.465,0.694l-5.379-3.601L146.73,127.412z"/>
+<path fill="#333333" d="M147.157,125.37l8.179,5.036l-0.338,0.548l-8.18-5.035L147.157,125.37z"/>
+<path fill="#333333" d="M148.854,123.91l5.637,3.178l-0.41,0.729l-5.637-3.178L148.854,123.91z"/>
+<path fill="#333333" d="M149.814,122.104l5.75,2.963l-0.383,0.742l-5.75-2.963L149.814,122.104z"/>
+<path fill="#333333" d="M150.709,120.241l5.861,2.735l-0.354,0.756l-5.861-2.734L150.709,120.241z"/>
+<path fill="#333333" d="M151.516,118.376l5.965,2.51l-0.322,0.771l-5.965-2.51L151.516,118.376z"/>
+<path fill="#333333" d="M151.539,116.303l8.988,3.389l-0.229,0.603l-8.986-3.388L151.539,116.303z"/>
+<path fill="#333333" d="M152.928,114.539l6.141,2.047l-0.266,0.792l-6.14-2.047L152.928,114.539z"/>
+<path fill="#333333" d="M153.525,112.57l6.211,1.811l-0.232,0.803l-6.212-1.812L153.525,112.57z"/>
+<path fill="#333333" d="M154.046,110.602l6.272,1.562l-0.201,0.812l-6.273-1.563L154.046,110.602z"/>
+<path fill="#333333" d="M154.482,108.585l6.336,1.326l-0.172,0.817l-6.334-1.326L154.482,108.585z"/>
+<path fill="#333333" d="M154.117,106.549l9.461,1.604l-0.107,0.634l-9.461-1.603L154.117,106.549z"/>
+<path fill="#333333" d="M155.132,104.559l6.417,0.833l-0.107,0.828l-6.416-0.833L155.132,104.559z"/>
+<path fill="#333333" d="M155.338,102.516l6.448,0.586l-0.075,0.832l-6.447-0.586L155.338,102.516z"/>
+<path fill="#333333" d="M155.477,100.476l6.459,0.34l-0.043,0.833l-6.459-0.339L155.477,100.476z"/>
+<path fill="#333333" d="M155.529,98.425l6.469,0.103l-0.014,0.835l-6.469-0.103L155.529,98.425z"/>
+<path fill="#333333" d="M154.777,96.482l9.6-0.213l0.014,0.643l-9.598,0.214L154.777,96.482z"/>
+<path fill="#333333" d="M155.406,94.336l6.458-0.391l0.051,0.833l-6.459,0.391L155.406,94.336z"/>
+<path fill="#333333" d="M155.232,92.29l6.438-0.627l0.081,0.831l-6.438,0.627L155.232,92.29z"/>
+<path fill="#333333" d="M154.979,90.257l6.407-0.874l0.112,0.827l-6.407,0.874L154.979,90.257z"/>
+<path fill="#333333" d="M154.639,88.227l6.377-1.121l0.146,0.823l-6.377,1.121L154.639,88.227z"/>
+<path fill="#333333" d="M153.539,86.475l9.384-2.029l0.138,0.629l-9.386,2.029L153.539,86.475z"/>
+<path fill="#333333" d="M153.756,84.251l6.264-1.604l0.207,0.809l-6.264,1.604L153.756,84.251z"/>
+<path fill="#333333" d="M153.188,82.293l6.203-1.852l0.237,0.801l-6.201,1.852L153.188,82.293z"/>
+<path fill="#333333" d="M152.545,80.339l6.13-2.088l0.271,0.791l-6.131,2.088L152.545,80.339z"/>
+<path fill="#333333" d="M151.84,78.426l6.036-2.324l0.301,0.779l-6.036,2.324L151.84,78.426z"/>
+<path fill="#333333" d="M150.427,76.915l8.819-3.784l0.254,0.592l-8.82,3.784L150.427,76.915z"/>
+<path fill="#333333" d="M150.199,74.675l5.841-2.777l0.358,0.754l-5.842,2.777L150.199,74.675z"/>
+<path fill="#333333" d="M149.271,72.855L155,69.852l0.389,0.74l-5.729,3.003L149.271,72.855z"/>
+<path fill="#333333" d="M148.271,71.069l5.614-3.22l0.415,0.726l-5.615,3.219L148.271,71.069z"/>
+<path fill="#333333" d="M147.204,69.314l5.481-3.435l0.442,0.707l-5.481,3.436L147.204,69.314z"/>
+<path fill="#333333" d="M145.529,68.108l7.936-5.401l0.362,0.531l-7.935,5.402L145.529,68.108z"/>
+<path fill="#333333" d="M144.887,65.962l5.215-3.836l0.494,0.673l-5.214,3.836L144.887,65.962z"/>
+<path fill="#333333" d="M143.63,64.343l5.062-4.031l0.521,0.653l-5.062,4.031L143.63,64.343z"/>
+<path fill="#333333" d="M142.307,62.78l4.904-4.228l0.546,0.634l-4.905,4.227L142.307,62.78z"/>
+<path fill="#333333" d="M140.932,61.255l4.74-4.401l0.568,0.612l-4.741,4.401L140.932,61.255z"/>
+<path fill="#333333" d="M139.052,60.387l6.774-6.806l0.456,0.454l-6.774,6.806L139.052,60.387z"/>
+<path fill="#333333" d="M138.008,58.389l4.393-4.752l0.613,0.567l-4.392,4.751L138.008,58.389z"/>
+<path fill="#333333" d="M136.467,57.041l4.207-4.916l0.635,0.543l-4.207,4.916L136.467,57.041z"/>
+<path fill="#333333" d="M134.871,55.746l4.021-5.07l0.654,0.52l-4.021,5.07L134.871,55.746z"/>
+<path fill="#333333" d="M133.227,54.52l3.825-5.224l0.675,0.493l-3.826,5.225L133.227,54.52z"/>
+<path fill="#333333" d="M131.211,54.016l5.371-7.966l0.534,0.36l-5.371,7.965L131.211,54.016z"/>
+<path fill="#333333" d="M129.803,52.251l3.414-5.503l0.711,0.441l-3.414,5.502L129.803,52.251z"/>
+<path fill="#333333" d="M128.047,51.223l3.198-5.626l0.726,0.413l-3.197,5.625L128.047,51.223z"/>
+<path fill="#333333" d="M126.244,50.255l2.982-5.739l0.739,0.386l-2.981,5.738L126.244,50.255z"/>
+<path fill="#333333" d="M124.404,49.366l2.757-5.853l0.755,0.356l-2.756,5.852L124.404,49.366z"/>
+<path fill="#333333" d="M122.325,49.252l3.754-8.835l0.592,0.252l-3.754,8.835L122.325,49.252z"/>
+<path fill="#333333" d="M120.621,47.796l2.304-6.047l0.781,0.297l-2.304,6.047L120.621,47.796z"/>
+<path fill="#333333" d="M118.693,47.118l2.066-6.13l0.791,0.267l-2.066,6.13L118.693,47.118z"/>
+<path fill="#333333" d="M116.725,46.524l1.832-6.212l0.801,0.236l-1.83,6.212L116.725,46.524z"/>
+<path fill="#333333" d="M114.779,46.004l1.582-6.273l0.812,0.204l-1.584,6.273L114.779,46.004z"/>
+<path fill="#333333" d="M112.713,46.28l1.998-9.385l0.629,0.135l-1.999,9.384L112.713,46.28z"/>
+<path fill="#333333" d="M110.762,45.182l1.102-6.377l0.822,0.143l-1.101,6.376L110.762,45.182z"/>
+<path fill="#333333" d="M108.746,44.895l0.854-6.417l0.828,0.109l-0.854,6.418L108.746,44.895z"/>
+<path fill="#333333" d="M106.686,44.667l0.607-6.438l0.831,0.078l-0.606,6.438L106.686,44.667z"/>
+<path fill="#333333" d="M104.646,44.531l0.36-6.458l0.833,0.046l-0.359,6.459L104.646,44.531z"/>
+<path fill="#333333" d="M102.68,45.202l0.183-9.598l0.644,0.013l-0.184,9.598L102.68,45.202z"/>
+<path fill="#333333" d="M100.542,44.489l-0.123-6.469l0.835-0.017l0.123,6.469L100.542,44.489z"/>
+<path fill="#333333" d="M98.505,44.581l-0.37-6.458l0.833-0.048l0.37,6.458L98.505,44.581z"/>
+<path fill="#333333" d="M96.458,44.747l-0.606-6.438l0.831-0.078l0.606,6.438L96.458,44.747z"/>
+<path fill="#333333" d="M94.423,45.004l-0.854-6.418l0.828-0.109l0.854,6.417L94.423,45.004z"/>
+<path fill="#333333" d="M92.632,46.025l-1.633-9.46l0.634-0.109l1.633,9.46L92.632,46.025z"/>
+<path fill="#333333" d="M90.413,45.722l-1.347-6.324l0.816-0.174l1.347,6.324L90.413,45.722z"/>
+<path fill="#333333" d="M88.408,46.207l-1.584-6.273l0.811-0.204l1.583,6.273L88.408,46.207z"/>
+<path fill="#333333" d="M86.447,46.767l-1.83-6.212l0.802-0.236l1.83,6.212L86.447,46.767z"/>
+<path fill="#333333" d="M84.515,47.387l-2.067-6.13l0.791-0.267l2.067,6.129L84.515,47.387z"/>
+<path fill="#333333" d="M82.944,48.742l-3.418-8.972l0.602-0.229l3.418,8.973L82.944,48.742z"/>
+<path fill="#333333" d="M80.687,48.877l-2.53-5.954l0.769-0.327l2.53,5.955L80.687,48.877z"/>
+<path fill="#333333" d="M78.817,49.73l-2.756-5.852l0.755-0.356l2.757,5.853L78.817,49.73z"/>
+<path fill="#333333" d="M77.015,50.641l-2.982-5.738l0.74-0.386l2.982,5.739L77.015,50.641z"/>
+<path fill="#333333" d="M75.205,51.646l-3.198-5.626l0.726-0.413l3.199,5.626L75.205,51.646z"/>
+<path fill="#333333" d="M73.931,53.274l-5.066-8.163l0.547-0.34l5.066,8.164L73.931,53.274z"/>
+<path fill="#333333" d="M71.764,53.824l-3.62-5.368l0.692-0.468l3.62,5.368L71.764,53.824z"/>
+<path fill="#333333" d="M70.097,55.016l-3.826-5.225l0.675-0.493l3.825,5.225L70.097,55.016z"/>
+<path fill="#333333" d="M68.474,56.267l-4.021-5.07l0.655-0.521l4.021,5.07L68.474,56.267z"/>
+<path fill="#333333" d="M66.896,57.584l-4.206-4.916l0.634-0.543l4.207,4.916L66.896,57.584z"/>
+<path fill="#333333" d="M65.941,59.427l-6.515-7.05l0.472-0.437l6.516,7.05L65.941,59.427z"/>
+<path fill="#333333" d="M63.906,60.392l-4.566-4.587l0.592-0.59l4.566,4.587L63.906,60.392z"/>
+<path fill="#333333" d="M62.501,61.867l-4.741-4.401l0.568-0.612l4.741,4.402L62.501,61.867z"/>
+<path fill="#333333" d="M61.145,63.415l-4.906-4.227l0.546-0.634l4.905,4.228L61.145,63.415z"/>
+<path fill="#333333" d="M59.848,64.996l-5.06-4.031l0.521-0.653l5.06,4.031L59.848,64.996z"/>
+<path fill="#333333" d="M59.263,66.991L51.526,61.3l0.381-0.519l7.736,5.691L59.263,66.991z"/>
+<path fill="#333333" d="M57.446,68.317l-5.358-3.63l0.469-0.691l5.358,3.63L57.446,68.317z"/>
+<path fill="#333333" d="M56.349,70.033l-5.492-3.425l0.442-0.709l5.491,3.425L56.349,70.033z"/>
+<path fill="#333333" d="M55.312,71.795l-5.615-3.219l0.415-0.726l5.615,3.22L55.312,71.795z"/>
+<path fill="#333333" d="M54.34,73.605l-5.738-2.993l0.386-0.74l5.739,2.992L54.34,73.605z"/>
+<path fill="#333333" d="M54.141,75.654l-8.667-4.12l0.275-0.58l8.667,4.119L54.141,75.654z"/>
+<path fill="#333333" d="M52.61,77.307l-5.944-2.551l0.33-0.768l5.944,2.551L52.61,77.307z"/>
+<path fill="#333333" d="M51.851,79.216l-6.037-2.314l0.299-0.779l6.037,2.314L51.851,79.216z"/>
+<path fill="#333333" d="M51.177,81.153l-6.13-2.088l0.27-0.791l6.13,2.088L51.177,81.153z"/>
+<path fill="#333333" d="M50.569,83.094l-6.201-1.851l0.238-0.801l6.202,1.852L50.569,83.094z"/>
+<path fill="#333333" d="M50.768,85.146l-9.293-2.38l0.159-0.623l9.293,2.38L50.768,85.146z"/>
+<path fill="#333333" d="M49.584,87.067l-6.325-1.368l0.177-0.816l6.325,1.368L49.584,87.067z"/>
+<path fill="#333333" d="M49.213,89.074l-6.377-1.121l0.146-0.823l6.376,1.121L49.213,89.074z"/>
+<path fill="#333333" d="M48.907,91.083l-6.406-0.874l0.112-0.827l6.407,0.874L48.907,91.083z"/>
+<path fill="#333333" d="M48.687,93.121l-6.438-0.628l0.081-0.831l6.438,0.628L48.687,93.121z"/>
+<path fill="#333333" d="M49.276,95.13l-9.583-0.564l0.038-0.643l9.583,0.564L49.276,95.13z"/>
+<path fill="#333333" d="M48.475,97.23l-6.47-0.144l0.019-0.835l6.47,0.144L48.475,97.23z"/>
+<path fill="#333333" d="M48.483,99.283l-6.47,0.103L42,98.551l6.469-0.103L48.483,99.283z"/>
+<path fill="#333333" d="M48.568,101.321l-6.458,0.35l-0.046-0.833l6.459-0.35L48.568,101.321z"/>
+<path fill="#333333" d="M48.737,103.374l-6.448,0.586l-0.075-0.832l6.448-0.587L48.737,103.374z"/>
+<path fill="#333333" d="M49.688,105.223l-9.521,1.235l-0.083-0.638l9.521-1.236L49.688,105.223z"/>
+<path fill="#333333" d="M49.291,107.421l-6.377,1.08l-0.139-0.823l6.376-1.08L49.291,107.421z"/>
+<path fill="#333333" d="M49.691,109.426l-6.335,1.327l-0.172-0.817l6.335-1.326L49.691,109.426z"/>
+<path fill="#333333" d="M50.159,111.432l-6.273,1.563l-0.202-0.812l6.274-1.562L50.159,111.432z"/>
+<path fill="#333333" d="M50.707,113.372l-6.212,1.81l-0.233-0.802l6.212-1.81L50.707,113.372z"/>
+<path fill="#333333" d="M51.998,115.01l-9.109,3.037l-0.204-0.609l9.11-3.037L51.998,115.01z"/>
+<path fill="#333333" d="M52.037,117.253l-6.058,2.283l-0.294-0.782l6.058-2.281L52.037,117.253z"/>
+<path fill="#333333" d="M52.807,119.146l-5.966,2.509l-0.323-0.771l5.965-2.51L52.807,119.146z"/>
+<path fill="#333333" d="M53.652,121.018l-5.862,2.735l-0.353-0.757l5.862-2.735L53.652,121.018z"/>
+<path fill="#333333" d="M54.565,122.846l-5.749,2.963l-0.382-0.742l5.749-2.963L54.565,122.846z"/>
+<path fill="#333333" d="M56.144,124.195l-8.362,4.716l-0.315-0.562l8.361-4.715L56.144,124.195z"/>
+<path fill="#333333" d="M56.606,126.384l-5.513,3.394l-0.438-0.711l5.513-3.395L56.606,126.384z"/>
+<path fill="#333333" d="M57.731,128.107l-5.379,3.6l-0.464-0.693l5.378-3.601L57.731,128.107z"/>
+<path fill="#333333" d="M58.918,129.779l-5.235,3.805l-0.491-0.676l5.235-3.805L58.918,129.779z"/>
+<path fill="#333333" d="M60.164,131.405l-5.08,4l-0.517-0.655l5.08-4.001L60.164,131.405z"/>
+<path fill="#333333" d="M61.971,132.432l-7.31,6.226l-0.417-0.49l7.31-6.226L61.971,132.432z"/>
+<path fill="#FFF200" d="M137.911,69.32l3.624-2.875c-5.367-6.779-12.527-12.29-21.146-15.7l-1.701,4.304
+ C126.523,58.147,133.029,63.156,137.911,69.32z"/>
+<path fill="#FFB700" d="M147.43,91.292l4.574-0.677c-1.314-8.823-4.932-17.174-10.469-24.17l-3.624,2.875
+ C142.945,75.68,146.232,83.27,147.43,91.292z"/>
+<path fill="#FFF200" d="M94.898,52.31l-0.677-4.574c-8.823,1.314-17.173,4.932-24.167,10.469l2.875,3.623
+ C79.287,56.793,86.878,53.505,94.898,52.31z"/>
+<path fill="#FFB700" d="M72.93,61.827l-2.875-3.623c-6.781,5.367-12.291,12.525-15.702,21.146l4.303,1.701
+ C61.755,73.216,66.765,66.707,72.93,61.827z"/>
+<path fill="#59DE00" d="M118.688,55.049l1.701-4.304c-8.621-3.408-17.613-4.285-26.167-3.01l0.677,4.574
+ C102.676,51.151,110.85,51.948,118.688,55.049z"/>
+</svg>
diff --git a/examples/declarative/dial/DialLibrary/needle.svg b/examples/declarative/dial/DialLibrary/needle.svg
new file mode 100644
index 0000000..dce7d7e
--- /dev/null
+++ b/examples/declarative/dial/DialLibrary/needle.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="210px" height="210px" viewBox="-98 -35 210 210" enable-background="new -98 -35 210 210"
+ xml:space="preserve">
+<defs>
+</defs>
+<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-102.5" y1="-13.5" x2="-94.5" y2="-13.5" gradientTransform="matrix(1 0 0 -1 102.5 18)">
+ <stop offset="0" style="stop-color:#EC1C24"/>
+ <stop offset="0.0782" style="stop-color:#E51B23"/>
+ <stop offset="0.3901" style="stop-color:#CA181F"/>
+ <stop offset="0.5495" style="stop-color:#F0C7C9"/>
+ <stop offset="0.5972" style="stop-color:#D98D90"/>
+ <stop offset="0.6452" style="stop-color:#C4595D"/>
+ <stop offset="0.687" style="stop-color:#B53339"/>
+ <stop offset="0.7206" style="stop-color:#AC1C22"/>
+ <stop offset="0.7418" style="stop-color:#A9141A"/>
+ <stop offset="1" style="stop-color:#EC1C24"/>
+</linearGradient>
+<path fill="url(#SVGID_1_)" d="M8,61c0,1.104-2.343,2-4,2l0,0c-1.657,0-4-0.896-4-2L2.5,2C2.5,0.896,3,0,4,0l0,0
+ c1,0,1.5,0.896,1.5,2L8,61z"/>
+</svg>
diff --git a/examples/declarative/dial/DialLibrary/needle_shadow.svg b/examples/declarative/dial/DialLibrary/needle_shadow.svg
new file mode 100644
index 0000000..6aab197
--- /dev/null
+++ b/examples/declarative/dial/DialLibrary/needle_shadow.svg
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="210px" height="210px" viewBox="-90 -30 210 210" enable-background="new -90 -30 210 210"
+ xml:space="preserve">
+<defs>
+</defs>
+<image overflow="visible" opacity="0.5" enable-background="new " width="26" height="81" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAABSCAYAAAClg6/xAAAACXBIWXMAAAsSAAALEgHS3X78AAAA
+GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAydJREFUeNrsmetu2zAMhUVaS9pu
+2Pu/5dY2vaSJ7dkAOZ8y1M3Jjw6zAUKx4ugLJZo+FkPYjhsc1Hidd/1o2tUwhKAhCC0LpQJIjcG0
+TwEDmAU3webBO7EInxXWi53h89AK038/D/xNbCdtBNgMOU32Ie1JgK53OZh6M0PuwHbi8SCQd7AP
+8PIC1iVguj6zJ/vJ7if7AfYgUJ3SIbF21TCdwtmb7wL5Ke09wAazbklYLIR7B949gFdRBu+kPco0
+dub3YwkWTMjjuul0KmwUyE762LkXi7Ac8E681eirArXANDLxFiC4FboaGGcgwckenWM2u4QUlBty
+IxtP2fQXcy03JmE2EHYSNK2BhUQiThmVPIsNGb8zSXlw1o2uCX12Mr9G4GieBDZImj2zYY9PgADn
+VeEfK9bJ3mN7ack8drrS+sVCBCoIYTvwDGERcqObH3OJ2Hpmp3J0QAwRTmvWLAUcE6DkmvHK0E+l
+LGqBUSFzsElXXMgk1JJBPGjuPKzNjWvU8VWw1JRQZuqv8owy0o9a3hu+1DTe9NhgG2yDJZPvWmsW
+qWt04yqtn9L5pT5q1fqlJ3SseGJXSzlPnFrrzXkRGAtTaIUOtoM594QqpWBUUMO2HZx+TxX/1Y6x
+oBnZmUbrmSfnXO3IFTrfrlupj1uikSpkXFch57IwSqybNyAXvneFUqtubE5Ra6RcreC5+gU+pw+p
+IO+2h+cG22BfEFaTiv6N19zS22Su3pL9LVfmRa/IkysYNG8BBjPoOSy1F5JW+/C65s1N9GQe7CN8
+rrv0AnuH784ZTy9gtvDWA2ge9GWy57DUaE5y/hL8os/F2saEVwh6m+ww2WNYKhXaPkv/Qa6rrjLZ
+CoVVT0EGmQd8nexpst+T/RJ7FPhrWOppn6CdE50MG5soo7FedgCY2pP0z98fw1JxGlIhiqUsrZtp
+OcuWsnozzQdZvzeBnQCY1BkM07cX04LPPix1mFEGPEKUHsXOJjqTNx9ndr1xHxgD6QR29qYwJ8co
+8cKHG854i2h1sM9lFqpItuxsZHo3/2imrbqam9tvtLAQblCBr71+DP/98UeAAQDKLu+cxVe7aAAA
+AABJRU5ErkJggg==">
+</image>
+</svg>
diff --git a/examples/declarative/dial/DialLibrary/overlay.svg b/examples/declarative/dial/DialLibrary/overlay.svg
new file mode 100644
index 0000000..8530dd5
--- /dev/null
+++ b/examples/declarative/dial/DialLibrary/overlay.svg
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="210px" height="210px" viewBox="-21.12 -18.396 210 210" enable-background="new -21.12 -18.396 210 210"
+ xml:space="preserve">
+<defs>
+</defs>
+<image overflow="visible" opacity="0.5" enable-background="new " width="48" height="48" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADEAAAAxCAYAAABznEEcAAAACXBIWXMAAAsSAAALEgHS3X78AAAA
+GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA/JJREFUeNrsWolum0AQZQHfOdrc
+//93bZO2OVwTx2YL0hvpaTK7C7iJUhSkJ2wMu/N2jp0ZnGWfx8c43BuPx9+9+s1/FBKOzs4YM0TC
+09kfSsod8JxGblzLjNVn1MY1/9YktNCCAuBrztCECC7YA3ytNxk3gAALXQIToFRkNAkWftfgBdgB
+TKozEdeDgAgmgk+BGWEKMkxEDibQCr5t8EzYAkKINXMwCV59WfV5gwWwBBa4PlUaYRKigVbYqsGm
+wR9gA1SknX0XIq4HgQkEFMGPGhwTVkRkEiHxQgTWDR4JT0Roi3uTRFwPAjMS/qTBaYMvwAkREbMq
+yC88kRAzEgIPDX4D9/guZJ67EHEJJ2YCKwjaCn/W4BznMxAZSqIV/idwh/M9flsrIqazlwktiA8s
+oIGWwAVwhfM5rh9DU7MO5vSMlX7EuAs8x894I+zWXUmwFkrY+BImcwbBbxpcN7jEtVPyCQm1oegk
+oXUDAkw8N+7dKzJOEykTvjBVWjiHBq6BltBXaEFWs1SmpPcJiVBzFc1yQ2NbtYeY+0fRgcAxBBUT
+ugEuDVOa014xoT2lJHLWtYII643wJeXcRcQXxJnFkUUDN/gsBLRJlLSyevcuAqmKIzPRm+E2FW41
+CZlANrQjRJ4LrLz4wQVFpGVgp3YR8D1sdjWtfAUSFUWonRWlLBIxU7pSfqCdMjfSc2ek6i6QqnP0
+qtQuvg2F2jJQG+SUH0mKsQKW5MRWnuQ6ZAie7ue9SLKBlcoA2PlZTp+pEGhlqhMiwoneJBCF+iSU
+obyM55kbpvqqVskTGSsPPqUBYyl33/rk4LnyRN3AUaQIFD+HFFg6oKTmcykSlvPlEbiBwqdMKzaf
+FRxMTaQqu/fqwnSeqw+JQUX8wKPXXHngQauor42C/l/0j7yRtYbms1o9pia8UdRr8OBDm2HeyHBT
+85kaCpGwuhKcw1gp8lAtHDxXHtECJ2KV6kyECnk/0ISYAM9TBZI/H/MJHlh3JdaAFPK6/q07OCX/
+VhvVnnQ/ZC7Om3ahBSs6pB0zKmAWgdTDRXqwMZ/bUca6Rm3d1tm3DX7g8y80D6RxoMm8IqGJcHdv
+Rs0yKx3IEl1vHzAf0fIDmgQtge8gcYtGwiO1cfYqoAQ1YeU0sYrMJUymplRbN9AsAkJCOh/rkBZS
+mnCRnMZKBVKheacqtk2CwC1M6cnQQpJE6N1DHilmaiUs18hb1XfdULvmXhH4BggB0UKlqrqsCwld
+eDhl59o8QgJzdSZR54m6fndKA0LgDgRECxLSzcg3ig7gqHuxo+mKj+b9xGjeFI3mnd1o3p6O5j12
+alfPsv/oHwVdx3uX/3Z8Hh/l+CvAAIH3kc3b00M7AAAAAElFTkSuQmCC" transform="matrix(1 0 0 1 57.8799 59.604)">
+</image>
+<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-26.0957" y1="-12.2373" x2="-17.2345" y2="-44.2323" gradientTransform="matrix(1 0 0 -1 102.5 51.208)">
+ <stop offset="0" style="stop-color:#FFFFFF"/>
+ <stop offset="1" style="stop-color:#000000"/>
+</linearGradient>
+<circle fill="url(#SVGID_1_)" cx="80.88" cy="79.604" r="15"/>
+<radialGradient id="SVGID_2_" cx="-28.9624" cy="-17.0811" r="25.2655" gradientTransform="matrix(1 0 0 -1 102.5 51.208)" gradientUnits="userSpaceOnUse">
+ <stop offset="0" style="stop-color:#FFFFFF"/>
+ <stop offset="1" style="stop-color:#616161"/>
+</radialGradient>
+<path fill="url(#SVGID_2_)" d="M80.88,92.603c-7.167,0-12.999-5.832-12.999-13c-0.001-7.166,5.832-12.999,12.999-12.999
+ s13,5.832,13,12.999C93.879,86.771,88.047,92.603,80.88,92.603L80.88,92.603z"/>
+<path opacity="0.5" fill="#FFFFFF" enable-background="new " d="M10.697,75.919c27.161-27.154,64.439-42.608,102.867-42.608
+ c11.422,0,22.744,1.386,33.739,4.018C133.183,14.903,108.235,0,79.768,0C35.712,0,0,35.714,0,79.768c0,2.589,0.14,5.14,0.387,7.648
+ C3.609,83.419,7.044,79.58,10.697,75.919z"/>
+</svg>
diff --git a/examples/declarative/dial/dial.qml b/examples/declarative/dial/dial.qml
new file mode 100644
index 0000000..ce43b01
--- /dev/null
+++ b/examples/declarative/dial/dial.qml
@@ -0,0 +1,14 @@
+<?qtfx namespacepath:=DialLibrary ?>
+<Rect color="white" width="210" height="240">
+ <!-- Dial with a slider to adjust it -->
+ <Dial id="Dial" value="{Slider.x-2}"/>
+ <Rect anchors.top="{Dial.bottom}" x="20" width="160" height="16" color="steelblue" gradientColor="lightsteelblue" radius="8" opacity="0.7">
+ <Rect id="Slider" anchors.top="{Dial.bottom}" x="2" y="2" width="30" height="12" color="lightgray" gradientColor="gray" radius="6">
+ <MouseRegion anchors.fill="{parent}"
+ drag.target="{parent}"
+ drag.axis="x"
+ drag.xmin="2"
+ drag.xmax="128"/>
+ </Rect>
+ </Rect>
+</Rect>
diff --git a/examples/declarative/easing/easing.qml b/examples/declarative/easing/easing.qml
new file mode 100644
index 0000000..f95d8c6
--- /dev/null
+++ b/examples/declarative/easing/easing.qml
@@ -0,0 +1,67 @@
+<Rect id="Window" width="640" height="{Layout.height}" color="white">
+
+ <resources>
+ <ListModel id="EasingTypes">
+ <ListItem><type>easeLinear</type></ListItem>
+ <ListItem><type>easeInQuad</type></ListItem>
+ <ListItem><type>easeOutQuad</type></ListItem>
+ <ListItem><type>easeInOutQuad</type></ListItem>
+ <ListItem><type>easeOutInQuad</type></ListItem>
+ <ListItem><type>easeInCubic</type></ListItem>
+ <ListItem><type>easeOutCubic</type></ListItem>
+ <ListItem><type>easeInOutCubic</type></ListItem>
+ <ListItem><type>easeOutInCubic</type></ListItem>
+ <ListItem><type>easeInQuart</type></ListItem>
+ <ListItem><type>easeOutQuart</type></ListItem>
+ <ListItem><type>easeInOutQuart</type></ListItem>
+ <ListItem><type>easeOutInQuart</type></ListItem>
+ <ListItem><type>easeInQuint</type></ListItem>
+ <ListItem><type>easeOutQuint</type></ListItem>
+ <ListItem><type>easeInOutQuint</type></ListItem>
+ <ListItem><type>easeOutInQuint</type></ListItem>
+ <ListItem><type>easeInSine</type></ListItem>
+ <ListItem><type>easeOutSine</type></ListItem>
+ <ListItem><type>easeInOutSine</type></ListItem>
+ <ListItem><type>easeOutInSine</type></ListItem>
+ <ListItem><type>easeInExpo</type></ListItem>
+ <ListItem><type>easeOutExpo</type></ListItem>
+ <ListItem><type>easeInOutExpo</type></ListItem>
+ <ListItem><type>easeOutInExpo</type></ListItem>
+ <ListItem><type>easeInCirc</type></ListItem>
+ <ListItem><type>easeOutCirc</type></ListItem>
+ <ListItem><type>easeInOutCirc</type></ListItem>
+ <ListItem><type>easeOutInCirc</type></ListItem>
+ <ListItem><type>easeInElastic</type></ListItem>
+ <ListItem><type>easeOutElastic</type></ListItem>
+ <ListItem><type>easeInOutElastic</type></ListItem>
+ <ListItem><type>easeOutInElastic</type></ListItem>
+ <ListItem><type>easeInBack</type></ListItem>
+ <ListItem><type>easeOutBack</type></ListItem>
+ <ListItem><type>easeInOutBack</type></ListItem>
+ <ListItem><type>easeOutInBack</type></ListItem>
+ <ListItem><type>easeOutBounce</type></ListItem>
+ <ListItem><type>easeInBounce</type></ListItem>
+ <ListItem><type>easeInOutBounce</type></ListItem>
+ <ListItem><type>easeOutInBounce</type></ListItem>
+ </ListModel>
+ </resources>
+
+ <VerticalLayout id="Layout" anchors.left="{Window.left}" anchors.right="{Window.right}">
+ <Repeater dataSource="{EasingTypes}">
+ <Component>
+ <Text id="Text" text="{type}" height="18" font.italic="true">
+ <x>
+ <SequentialAnimation id="Anim">
+ <NumericAnimation from="0" to="{Window.width / 2}" easing="{type}" duration="1000"/>
+ <PauseAnimation duration="300"/>
+ <NumericAnimation to="0" from="{Window.width / 2}" easing="{type}" duration="1000"/>
+ </SequentialAnimation>
+ </x>
+ <children>
+ <MouseRegion onClicked="Anim.running=true" anchors.fill="{parent}"/>
+ </children>
+ </Text>
+ </Component>
+ </Repeater>
+ </VerticalLayout>
+</Rect>
diff --git a/examples/declarative/follow/follow.qml b/examples/declarative/follow/follow.qml
new file mode 100644
index 0000000..0f3e772
--- /dev/null
+++ b/examples/declarative/follow/follow.qml
@@ -0,0 +1,35 @@
+<Rect width="320" height="240" color="#ffffff">
+ <Rect id="Rect" y="{200}" color="#00ff00" width="60" height="20">
+ <y>
+ <SequentialAnimation running="true" repeat="true">
+ <NumericAnimation to="{200}" easing="easeOutBounce(amplitude:180)" duration="2000" />
+ <PauseAnimation duration="1000" />
+ </SequentialAnimation>
+ </y>
+ </Rect>
+ <!-- Velocity -->
+ <Rect x="{Rect.width}" color="#ff0000" width="{Rect.width}" height="20">
+ <y>
+ <Follow source="{Rect.y}" velocity="200"/>
+ </y>
+ </Rect>
+ <Text x="{Rect.width}" y="220" text="Velocity"/>
+ <!-- Spring -->
+ <Rect x="{Rect.width * 2}" color="#ff0000" width="{Rect.width}" height="20">
+ <y>
+ <Follow source="{Rect.y}" spring="1.2" damping="0.1"/>
+ </y>
+ </Rect>
+ <Text x="{Rect.width * 2}" y="220" text="Spring"/>
+ <!-- Follow mouse -->
+ <MouseRegion id="Mouse" anchors.fill="{parent}">
+ <Rect width="20" height="20" radius="10" color="#0000ff">
+ <x>
+ <Follow source="{Mouse.mouseX-10}" spring="1.0" damping="0.05"/>
+ </x>
+ <y>
+ <Follow source="{Mouse.mouseY-10}" spring="1.0" damping="0.05"/>
+ </y>
+ </Rect>
+ </MouseRegion>
+</Rect>
diff --git a/examples/declarative/follow/pong.qml b/examples/declarative/follow/pong.qml
new file mode 100644
index 0000000..4fbf323
--- /dev/null
+++ b/examples/declarative/follow/pong.qml
@@ -0,0 +1,55 @@
+<Rect id="Page" width="640" height="480" color="#000000">
+ <!-- Make a ball to bounce -->
+ <Rect id="Ball" x="20" width="20" height="20" color="#00ee00" z="1">
+ <properties>
+ <!-- Add a property for the target y coordinate -->
+ <Property name="targetY" value="{Page.height-10}"/>
+ <Property name="direction" value="right"/>
+ </properties>
+ <x>
+ <!-- Move the ball to the right and back to the left repeatedly -->
+ <SequentialAnimation running="true" repeat="true">
+ <NumericAnimation to="{Page.width-40}" duration="2000"/>
+ <SetPropertyAction target="{Ball}" property="direction" value="left"/>
+ <NumericAnimation to="20" duration="2000"/>
+ <SetPropertyAction target="{Ball}" property="direction" value="right"/>
+ </SequentialAnimation>
+ </x>
+ <y>
+ <!-- Make y follow the target y coordinate, with a velocity of 200 -->
+ <Follow source="{Ball.targetY}" velocity="200"/>
+ </y>
+ <onTopChanged>
+ <!-- Detect the ball hitting the top or bottom of the view and bounce it -->
+ if (y &lt;= 0)
+ targetY = Page.height-20;
+ else if (y &gt;= Page.height-20)
+ targetY = 0;
+ </onTopChanged>
+ </Rect>
+ <!--
+ Place bats to the left and right of the view, following the y
+ coordinates of the ball.
+ -->
+ <Rect id="LeftBat" color="#00ee00" x="2" width="20" height="90">
+ <y>
+ <Follow source="{Ball.y-45}" velocity="300" enabled="{Ball.direction == 'left'}"/>
+ </y>
+ </Rect>
+ <Rect id="RightBat" x="{Page.width-22}" color="#00ee00" width="20" height="90">
+ <y>
+ <Follow source="{Ball.y-45}" velocity="300" enabled="{Ball.direction == 'right'}"/>
+ </y>
+ </Rect>
+
+ <!--
+ The rest, to make it look realistic, if neither ever scores...
+ -->
+ <Rect color="#00ee00" width="40" height="60" x="{320-80}"/>
+ <Rect color="#000000" width="20" height="40" x="{320-70}" y="10"/>
+ <Rect color="#00ee00" width="40" height="60" x="{320+40}"/>
+ <Rect color="#000000" width="20" height="40" x="{320+50}" y="10"/>
+ <Repeater dataSource="{24}">
+ <Rect color="#00ee00" width="10" height="10" x="{320-5}" y="{index*20}"/>
+ </Repeater>
+</Rect>
diff --git a/examples/declarative/listview/content/MediaButton.qml b/examples/declarative/listview/content/MediaButton.qml
new file mode 100644
index 0000000..c92305a
--- /dev/null
+++ b/examples/declarative/listview/content/MediaButton.qml
@@ -0,0 +1,21 @@
+<Item id="Container">
+ <signals>
+ <Signal name="clicked"/>
+ </signals>
+
+ <properties>
+ <Property name="text"/>
+ </properties>
+
+ <Image id="Image" src="pics/button.png"/>
+ <Image id="Pressed" src="pics/button-pressed.png" opacity="0"/>
+ <MouseRegion id="MouseRegion" anchors.fill="{Image}" onClicked="Container.clicked.emit();"/>
+ <Text font.bold="true" color="white" anchors.centeredIn="{Image}" text="{Container.text}"/>
+ <width>{Image.width}</width>
+
+ <states>
+ <State name="Pressed" when="{MouseRegion.pressed == true}">
+ <SetProperties target="{Pressed}" opacity="1"/>
+ </State>
+ </states>
+</Item>
diff --git a/examples/declarative/listview/content/pics/button-pressed.png b/examples/declarative/listview/content/pics/button-pressed.png
new file mode 100644
index 0000000..e434d32
--- /dev/null
+++ b/examples/declarative/listview/content/pics/button-pressed.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/button.png b/examples/declarative/listview/content/pics/button.png
new file mode 100644
index 0000000..56a63ce
--- /dev/null
+++ b/examples/declarative/listview/content/pics/button.png
Binary files differ
diff --git a/examples/declarative/listview/content/pics/fruit-salad.jpg b/examples/declarative/listview/content/pics/fruit-salad.jpg
new file mode 100644
index 0000000..da5a6b1
--- /dev/null
+++ b/examples/declarative/listview/content/pics/fruit-salad.jpg
Binary files differ
diff --git a/examples/declarative/listview/content/pics/hamburger.jpg b/examples/declarative/listview/content/pics/hamburger.jpg
new file mode 100644
index 0000000..d0a15be
--- /dev/null
+++ b/examples/declarative/listview/content/pics/hamburger.jpg
Binary files differ
diff --git a/examples/declarative/listview/content/pics/lemonade.jpg b/examples/declarative/listview/content/pics/lemonade.jpg
new file mode 100644
index 0000000..db445c9
--- /dev/null
+++ b/examples/declarative/listview/content/pics/lemonade.jpg
Binary files differ
diff --git a/examples/declarative/listview/content/pics/pancakes.jpg b/examples/declarative/listview/content/pics/pancakes.jpg
new file mode 100644
index 0000000..60c4396
--- /dev/null
+++ b/examples/declarative/listview/content/pics/pancakes.jpg
Binary files differ
diff --git a/examples/declarative/listview/content/pics/vegetable-soup.jpg b/examples/declarative/listview/content/pics/vegetable-soup.jpg
new file mode 100644
index 0000000..9dce332
--- /dev/null
+++ b/examples/declarative/listview/content/pics/vegetable-soup.jpg
Binary files differ
diff --git a/examples/declarative/listview/dummydata/MyPetsModel.qml b/examples/declarative/listview/dummydata/MyPetsModel.qml
new file mode 100644
index 0000000..5af7fbf
--- /dev/null
+++ b/examples/declarative/listview/dummydata/MyPetsModel.qml
@@ -0,0 +1,51 @@
+<!--
+ListModel allows free form list models to be defined and populated.
+Be sure to name the file the same as the id.
+-->
+<ListModel id="MyPetsModel">
+ <Pet>
+ <name>Rover</name>
+ <type>Dog</type>
+ <age>5</age>
+ </Pet>
+ <Pet>
+ <name>Whiskers</name>
+ <type>Cat</type>
+ <age>2</age>
+ </Pet>
+ <Pet>
+ <name>Warren</name>
+ <type>Rabbit</type>
+ <age>2</age>
+ </Pet>
+ <Pet>
+ <name>Polly</name>
+ <type>Parrot</type>
+ <age>12</age>
+ </Pet>
+ <Pet>
+ <name>Spot</name>
+ <type>Dog</type>
+ <age>9</age>
+ </Pet>
+ <Pet>
+ <name>Tiny</name>
+ <type>Elephant</type>
+ <age>15</age>
+ </Pet>
+ <Pet>
+ <name>Penny</name>
+ <type>Turtle</type>
+ <age>4</age>
+ </Pet>
+ <Pet>
+ <name>Joey</name>
+ <type>Kangaroo</type>
+ <age>1</age>
+ </Pet>
+ <Pet>
+ <name>Kimba</name>
+ <type>Bunny</type>
+ <age>65</age>
+ </Pet>
+</ListModel>
diff --git a/examples/declarative/listview/dummydata/Recipies.qml b/examples/declarative/listview/dummydata/Recipies.qml
new file mode 100644
index 0000000..49bc610
--- /dev/null
+++ b/examples/declarative/listview/dummydata/Recipies.qml
@@ -0,0 +1,112 @@
+<ListModel id="Recipies">
+ <Recipe title="Pancakes" picture="content/pics/pancakes.jpg">
+ <ingredients>
+ <![CDATA[
+ <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>
+ ]]>
+ </ingredients>
+ <method>
+ <![CDATA[
+ <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>
+ ]]>
+ </method>
+ </Recipe>
+ <Recipe title="Fruit Salad" picture="content/pics/fruit-salad.jpg">
+ <ingredients>
+ * Seasonal Fruit
+ </ingredients>
+ <method>
+ * Chop fruit and place in a bowl.
+ </method>
+ </Recipe>
+ <Recipe title="Vegetable Soup" picture="content/pics/vegetable-soup.jpg">
+ <ingredients>
+ <![CDATA[
+ <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>
+ ]]>
+ </ingredients>
+ <method>
+ <![CDATA[
+ <html>
+ <ol>
+ <li> Chop vegetables.
+ <li> Boil in water until vegetables soften.
+ <li> Season with salt and pepper to taste.
+ </ol>
+ </html>
+ ]]>
+ </method>
+ </Recipe>
+ <Recipe title="Hamburger" picture="content/pics/hamburger.jpg">
+ <ingredients>
+ <![CDATA[
+ <html>
+ <ul>
+ <li> 500g minced beef
+ <li> Seasoning
+ <li> lettuce, tomato, onion, cheese
+ <li> 1 hamburger bun for each burger
+ </ul>
+ </html>
+ ]]>
+ </ingredients>
+ <method>
+ <![CDATA[
+ <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>
+ ]]>
+ </method>
+ </Recipe>
+ <Recipe title="Lemonade" picture="content/pics/lemonade.jpg">
+ <ingredients>
+ <![CDATA[
+ <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>
+ ]]>
+ </ingredients>
+ <method>
+ <![CDATA[
+ <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>
+ ]]>
+ </method>
+ </Recipe>
+</ListModel>
diff --git a/examples/declarative/listview/highlight.qml b/examples/declarative/listview/highlight.qml
new file mode 100644
index 0000000..5ce7acb
--- /dev/null
+++ b/examples/declarative/listview/highlight.qml
@@ -0,0 +1,56 @@
+<Rect width="400" height="300" color="white">
+
+ <!--
+ MyPets model is defined in dummydata/MyPetsModel.qml
+ The viewer automatically loads files in dummydata/* to assist
+ development without a real data source.
+ This one contains my pets.
+ -->
+
+ <!--
+ 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="50">
+ <VerticalLayout>
+ <Text text="{'Name: ' + name}"/>
+ <Text text="{'Type: ' + type}"/>
+ <Text text="{'Age: ' + age}"/>
+ </VerticalLayout>
+
+ <!--
+ Use the ListView.isCurrentItem attached property to
+ indent the item if it is the current item.
+ -->
+ <states>
+ <State name="Current" when="{Wrapper.ListView.isCurrentItem}">
+ <SetProperty target="{Wrapper}" property="x" value="10"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition>
+ <NumericAnimation properties="x" duration="200" />
+ </Transition>
+ </transitions>
+ </Item>
+ </Component>
+
+ <!--
+ Specify a highlight with custom movement. Note that autoHighlight
+ is set to false in the ListView so that we can control how the
+ highlight moves to the current item.
+ -->
+ <Component id="PetHighlight">
+ <Rect width="200" height="50" color="#FFFF88">
+ <y>
+ <Follow source="{List1.current.y}" spring="3" damping="0.1"/>
+ </y>
+ </Rect>
+ </Component>
+
+ <ListView id="List1" width="200" height="{parent.height}" model="{MyPetsModel}"
+ delegate="{PetDelegate}" highlight="{PetHighlight}" autoHighlight="false"
+ focus="true"/>
+
+</Rect>
diff --git a/examples/declarative/listview/listview.qml b/examples/declarative/listview/listview.qml
new file mode 100644
index 0000000..08c8f18
--- /dev/null
+++ b/examples/declarative/listview/listview.qml
@@ -0,0 +1,81 @@
+<Rect width="600" height="300" color="white">
+
+ <!--
+ MyPets model is defined in dummydata/MyPetsModel.qml
+ The viewer automatically loads files in dummydata/* to assist
+ development without a real data source.
+ This one contains my pets.
+ -->
+
+ <!--
+ 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="50">
+ <VerticalLayout>
+ <Text text="{'Name: ' + name}"/>
+ <Text text="{'Type: ' + type}"/>
+ <Text text="{'Age: ' + age}"/>
+ </VerticalLayout>
+ </Item>
+ </Component>
+
+ <!--
+ Define a highlight component. Just one of these will be instantiated
+ by each ListView and placed behind the current item.
+ -->
+ <Component id="PetHighlight">
+ <Rect color="#FFFF88"/>
+ </Component>
+
+ <!--
+ Show the model in three lists, with different currentItemPositioning.
+ currentItemPositioning determines how the list behaves when the
+ current item changes. Note that the second and third ListView
+ set their currentIndex to be the same as the first, and that
+ the first ListView is given keyboard focus.
+
+ The default mode, Free, allows the currentItem to move freely
+ within the visible area. If it would move outside the visible
+ area, the view is scrolled to keep it visible.
+
+ Snap currentItemPositioning attempts to keep the current item
+ aligned with the snapPosition by scrolling the view, however the
+ items will not scroll beyond the beginning or end of the view.
+
+ SnapAuto currentItemPositioning always keeps the current item on
+ the snapPosition by scrolling the view. It also automatically
+ sets the current item as is scrolled with the mouse. Note
+ that the first ListView sets its currentIndex to be equal to
+ the third ListView's currentIndex. By flicking List3 with
+ the mouse, the current index of List1 will be changed.
+ -->
+
+ <ListView id="List1" width="200" height="{parent.height}" model="{MyPetsModel}"
+ delegate="{PetDelegate}" highlight="{PetHighlight}"
+ currentIndex="{List3.currentIndex}" focus="true"/>
+
+ <ListView id="List2" x="200" width="200" height="{parent.height}" model="{MyPetsModel}"
+ delegate="{PetDelegate}" highlight="{PetHighlight}"
+ currentItemPositioning="Snap" snapPosition="125"
+ currentIndex="{List1.currentIndex}"/>
+
+ <ListView id="List3" x="400" width="200" height="{parent.height}" model="{MyPetsModel}"
+ delegate="{PetDelegate}"
+ currentItemPositioning="SnapAuto" snapPosition="125"
+ currentIndex="{List1.currentIndex}">
+ <children>
+ <!--
+ Position a static highlight rather than a normal highlight so that
+ when the view is flicked, the highlight does not move.
+ By positioning the highlight at the same position as the snapPosition
+ the item under the highlight will always be the current item.
+ Note that we specify the 'children' property. This is because
+ the default property of a ListView is 'delegate'.
+ -->
+ <Rect y="{List3.yPosition+125}" width="200" height="50" color="#FFFF88" z="0"/>
+ </children>
+ </ListView>
+
+</Rect>
diff --git a/examples/declarative/listview/recipes.qml b/examples/declarative/listview/recipes.qml
new file mode 100644
index 0000000..7d32532
--- /dev/null
+++ b/examples/declarative/listview/recipes.qml
@@ -0,0 +1,83 @@
+<!-- This example illustrates expanding a list item to show a more detailed view -->
+<?qtfx namespacepath:=content ?>
+<Rect id="page" width="400" height="280" color="black">
+ <resources>
+ <!--
+ Delegate for the recipes. This delegate has two modes:
+ 1. the list mode (default), which just shows the picture and title of the recipe.
+ 2. the details mode, which also shows the ingredients and method.
+ -->
+ <Component id="recipeDelegate">
+ <Item id="wrapper" x="10" width="{List.width-20}">
+ <!--
+ 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 "SetProperty" line for each element we
+ want to fade.
+ -->
+ <properties><Property name="detailsOpacity" value="0" type="real"/></properties>
+ <!-- A simple rounded rectangle for the background -->
+ <Rect id="background" x="1" y="2" width="{parent.width-2}" height="{parent.height-4}" color="#FEFFEE" pen.color="#FFBE4F" 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.
+ -->
+ <MouseRegion id="pageMouse" anchors.fill="{parent}" onClicked="wrapper.state = 'Details'"/>
+ <!--
+ Layout the page. Picture, title and ingredients at the top, method at the
+ bottom. Note that elements that should not be visible in the list
+ mode have their opacity set to wrapper.detailsOpacity.
+ -->
+ <VerticalLayout id="topLayout" width="{parent.width-20}" margin="10" spacing="10">
+ <HorizontalLayout spacing="10" height="{recipePic.height}">
+ <Image id="recipePic" src="{picture}" width="48" height="48"/>
+ <VerticalLayout height="{recipePic.height}" spacing="5" width="{background.width-recipePic.width-20}">
+ <Text id="name" text="{title}" font.bold="true" font.size="16"/>
+ <Text opacity="{wrapper.detailsOpacity}" text="Ingredients" font.size="12" font.bold="true"/>
+ <Text opacity="{wrapper.detailsOpacity}" text="{ingredients}" wrap="true" width="{parent.width}"/>
+ </VerticalLayout>
+ </HorizontalLayout>
+ <VerticalLayout id="details" opacity="{wrapper.detailsOpacity}">
+ <Text text="Method" font.size="12" font.bold="true"/>
+ <Text text="{method}" wrap="true" width="{topLayout.width}"/>
+ </VerticalLayout>
+ </VerticalLayout>
+ <!-- A button to close the detailed view, i.e. set the state back to default (''). -->
+ <MediaButton anchors.right="{background.right}" anchors.rightMargin="5" y="10" opacity="{wrapper.detailsOpacity}" text="Close" onClicked="wrapper.state = ''"/>
+ <!-- Make the default height equal the hight of the picture, plus margin. -->
+ <height>68</height>
+
+ <states>
+ <State name="Details">
+ <SetProperty target="{background}" property="color" value="white" />
+ <!-- Make the picture bigger -->
+ <SetProperties target="{recipePic}" width="128" height="128" />
+ <!-- Make details visible -->
+ <SetProperties target="{wrapper}" detailsOpacity="1" x="0"/>
+ <!-- Make the detailed view fill the entire list area -->
+ <SetProperty target="{wrapper}" property="height" value="{List.height}"/>
+ <SetProperty target="{wrapper}" property="width" value="{List.width}"/>
+ <!-- Move the list so that this item is at the top. -->
+ <SetProperty target="{wrapper.ListView.view}" property="yPosition" value="{wrapper.y}"/>
+ <!-- Disallow flicking while we're in detailed view -->
+ <SetProperty target="{wrapper.ListView.view}" property="locked" value="1"/>
+ </State>
+ </states>
+
+ <transitions>
+ <Transition>
+ <!-- Make the state changes smooth -->
+ <ParallelAnimation>
+ <ColorAnimation duration="500" />
+ <NumericAnimation duration="300" properties="detailsOpacity,x,yPosition,height,width"/>
+ </ParallelAnimation>
+ </Transition>
+ </transitions>
+ </Item>
+ </Component>
+ </resources>
+
+ <!-- The actual list -->
+ <ListView id="List" model="{Recipies}" anchors.fill="{parent}" clip="true" delegate="{recipeDelegate}"/>
+</Rect>
diff --git a/examples/declarative/minehunt/Description.qml b/examples/declarative/minehunt/Description.qml
new file mode 100644
index 0000000..5bda5f8
--- /dev/null
+++ b/examples/declarative/minehunt/Description.qml
@@ -0,0 +1,10 @@
+<Item id="Page" height="{MyText.height + 20}" >
+ <properties><Property name="text" /></properties>
+ <MouseRegion anchors.fill="{parent}" drag.target="{Page}" drag.axis="xy" drag.xmin="0" drag.xmax="1000" drag.ymin="0" drag.ymax="1000"/>
+ <Rect radius="10" anchors.fill="{parent}" color="lightsteelblue" />
+ <Item x="10" y="10" width="{parent.width - 20}" height="{parent.height - 20}">
+ <Text id="MyText" text="{Page.text}" width="{parent.width}" clip="true" wrap="true"/>
+ </Item>
+
+ <filter><Shadow xOffset="5" yOffset="5" /></filter>
+</Item>
diff --git a/examples/declarative/minehunt/Explosion.qml b/examples/declarative/minehunt/Explosion.qml
new file mode 100644
index 0000000..aec685b
--- /dev/null
+++ b/examples/declarative/minehunt/Explosion.qml
@@ -0,0 +1,6 @@
+<Item>
+ <properties>
+ <Property name="explode" type="Bool" value="false"/>
+ </properties>
+ <Particles width="38" height="21" lifeSpan="3600000" lifeSpanDeviation="0" src="pics/star.png" count="200" angle="270" angleDeviation="360" velocity="100" velocityDeviation="20" z="100" emitting="{explode}"/>
+</Item>
diff --git a/examples/declarative/minehunt/main.cpp b/examples/declarative/minehunt/main.cpp
new file mode 100644
index 0000000..9db717b
--- /dev/null
+++ b/examples/declarative/minehunt/main.cpp
@@ -0,0 +1,312 @@
+#include "qmlbindablevalue.h"
+#include "qmlengine.h"
+#include "qmlcontext.h"
+#include "qml.h"
+#include <qfxitem.h>
+#include <qfxview.h>
+
+#include <QWidget>
+#include <QApplication>
+#include <QFile>
+#include <QTime>
+#include <QTimer>
+#include <QVBoxLayout>
+#include <QFileInfo>
+
+QString fileName = "minehunt.qml";
+
+class Tile : public QObject
+{
+ Q_OBJECT
+public:
+ Tile() : _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;
+};
+
+QML_DECLARE_TYPE(Tile);
+QML_DEFINE_TYPE(Tile,Tile);
+
+class MyWidget : public QWidget
+{
+Q_OBJECT
+public:
+ MyWidget(int = 370, int = 480, QWidget *parent=0, Qt::WindowFlags flags=0);
+ ~MyWidget();
+
+ Q_PROPERTY(QList<Tile *> *tiles READ tiles);
+ QList<Tile *> *tiles() { return &_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 void flip(int row, int col);
+ Q_INVOKABLE void 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; }
+ Tile *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();}
+
+ QFxView *canvas;
+
+ QList<Tile *> _tiles;
+ int numCols;
+ int numRows;
+ bool playing;
+ bool won;
+ int remaining;
+ int nMines;
+ int nFlags;
+};
+
+MyWidget::MyWidget(int width, int height, QWidget *parent, Qt::WindowFlags flags)
+: QWidget(parent, flags), canvas(0), numCols(9), numRows(9), playing(true), won(false)
+{
+ setObjectName("mainWidget");
+ srand(QTime(0,0,0).secsTo(QTime::currentTime()));
+
+ //initialize array
+ for(int ii = 0; ii < numRows * numCols; ++ii) {
+ _tiles << new Tile;
+ }
+
+ reset();
+
+ QVBoxLayout *vbox = new QVBoxLayout;
+ vbox->setMargin(0);
+ setLayout(vbox);
+
+ canvas = new QFxView(this);
+ canvas->setFixedSize(width, height);
+ vbox->addWidget(canvas);
+
+ QFile file(fileName);
+ file.open(QFile::ReadOnly);
+ QString xml = file.readAll();
+ canvas->setXml(xml, fileName);
+
+ QmlContext *ctxt = canvas->rootContext();
+ ctxt->activate();
+ ctxt->addDefaultObject(this);
+ ctxt->deactivate();
+
+ canvas->execute();
+}
+
+MyWidget::~MyWidget()
+{
+}
+
+void MyWidget::setBoard()
+{
+ foreach(Tile* 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);
+
+ Tile* 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++) {
+ Tile* t = tile(r, c);
+ if (t && !t->hasMine()) {
+ int hint = getHint(r,c);
+ t->setHint(hint);
+ }
+ }
+
+ setPlaying(true);
+}
+
+void MyWidget::reset()
+{
+ foreach(Tile* t, _tiles){
+ t->unflip();
+ t->setHasFlag(false);
+ }
+ nMines = 12;
+ nFlags = 0;
+ setPlaying(false);
+ QTimer::singleShot(900,this, SLOT(setBoard()));
+}
+
+int MyWidget::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++) {
+ Tile* t = tile(r, c);
+ if (t && t->hasMine())
+ hint++;
+ }
+ return hint;
+}
+
+void MyWidget::flip(int row, int col)
+{
+ if(!playing)
+ return;
+
+ Tile *t = tile(row, col);
+ if (!t || t->hasFlag())
+ return;
+
+ if(t->flipped()){
+ int flags = 0;
+ for (int c = col-1; c <= col+1; c++)
+ for (int r = row-1; r <= row+1; r++) {
+ Tile *nearT = tile(r, c);
+ if(!nearT || nearT == t)
+ continue;
+ if(nearT->hasFlag())
+ flags++;
+ }
+ if(!t->hint() || t->hint() != flags)
+ return;
+ for (int c = col-1; c <= col+1; c++)
+ for (int r = row-1; r <= row+1; r++) {
+ Tile *nearT = tile(r, c);
+ if (nearT && !nearT->flipped() && !nearT->hasFlag()) {
+ flip( r, c );
+ }
+ }
+ return;
+ }
+
+ t->flip();
+
+ if (t->hint() == 0) {
+ for (int c = col-1; c <= col+1; c++)
+ for (int r = row-1; r <= row+1; r++) {
+ Tile* 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++) {
+ Tile* t = tile(r, c);
+ if (t && t->hasMine()) {
+ flip(r, c);
+ }
+ }
+ won = false;
+ hasWonChanged();
+ setPlaying(false);
+ }
+
+ remaining--;
+ if(!remaining){
+ won = true;
+ hasWonChanged();
+ setPlaying(false);
+ }
+}
+
+void MyWidget::flag(int row, int col)
+{
+ Tile *t = tile(row, col);
+ if(!t)
+ return;
+
+ t->setHasFlag(!t->hasFlag());
+ nFlags += (t->hasFlag()?1:-1);
+ emit numFlagsChanged();
+}
+/////////////////////////////////////////////////////////
+
+int main(int argc, char ** argv)
+{
+ QApplication app(argc, argv);
+
+ bool frameless = false;
+
+ int width = 370;
+ int height = 480;
+
+ for (int i = 1; i < argc; ++i) {
+ QString arg = argv[i];
+ if (arg == "-frameless") {
+ frameless = true;
+ } else if(arg == "-width" && i < (argc - 1)) {
+ ++i;
+ width = ::atoi(argv[i]);
+ } else if(arg == "-height" && i < (argc - 1)) {
+ ++i;
+ height = ::atoi(argv[i]);
+ } else if (arg[0] != '-') {
+ fileName = arg;
+ }
+ }
+
+ MyWidget wid(width, height, 0, frameless ? Qt::FramelessWindowHint : Qt::Widget);
+ wid.show();
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/examples/declarative/minehunt/minehunt.pro b/examples/declarative/minehunt/minehunt.pro
new file mode 100644
index 0000000..08b6254
--- /dev/null
+++ b/examples/declarative/minehunt/minehunt.pro
@@ -0,0 +1,8 @@
+SOURCES = main.cpp
+
+QT += script declarative
+
+target.path = $$[QT_INSTALL_EXAMPLES]/declarative/minehunt
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS minehunt.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/declarative/minehunt
+INSTALLS += target sources
diff --git a/examples/declarative/minehunt/minehunt.qml b/examples/declarative/minehunt/minehunt.qml
new file mode 100644
index 0000000..9cde164
--- /dev/null
+++ b/examples/declarative/minehunt/minehunt.qml
@@ -0,0 +1,73 @@
+<Item id="field" width="370" height="480">
+ <properties>
+ <Property name="clickx" type="Int" value="0"/>
+ <Property name="clicky" type="Int" value="0"/>
+ </properties>
+ <resources>
+ <Component id="tile">
+ <Flipable id="flipable" width="40" height="40">
+ <transform>
+ <Axis id="axis" xStart="20" xEnd="20" yStart="20" yEnd="0" />
+ </transform>
+ <front>
+ <Image src="pics/cachepix-boxless.sci" width="40" height="40">
+ <Image anchors.horizontalCenter="{parent.horizontalCenter}"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="pics/flag.png" opacity="{modelData.hasFlag}">
+ <opacity>
+ <Behaviour>
+ <NumericAnimation property="opacity" duration="250"/>
+ </Behaviour>
+ </opacity>
+ </Image>
+ </Image>
+ </front>
+ <back>
+ <Image src="pics/cachepix-black.sci" width="40" height="40">
+ <Text anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}"
+ text="{modelData.hint}" color="white" font.bold="true"
+ opacity="{modelData.hasMine == false &amp;&amp; modelData.hint > 0}"/>
+ <Image anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}"
+ src="pics/bomb.png" opacity="{modelData.hasMine}"/>
+ <Explosion anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}" explode="{modelData.hasMine==true &amp;&amp; modelData.flipped==true}"/>
+ </Image>
+ </back>
+ <states>
+ <State name="back" when="{modelData.flipped == true}">
+ <SetProperty target="{axis}" property="rotation" value="180" />
+ </State>
+ </states>
+ <transitions>
+ <Transition>
+ <SequentialAnimation>
+ <PauseAnimation duration="{var ret = Math.abs(flipable.parent.x-field.clickx) + Math.abs(flipable.parent.y-field.clicky); if (ret > 0) {if(modelData.hasMine==true &amp;&amp; modelData.flipped==true){ret*3;}else{ret;}} else {0}}"/>
+ <NumericAnimation easing="easeInOutQuad" properties="rotation"/>
+ </SequentialAnimation>
+ </Transition>
+ </transitions>
+ <MouseRegion anchors.fill="{parent}"
+ onClicked="field.clickx = flipable.parent.x; field.clicky = flipable.parent.y; row = Math.floor(index/9); col = index - (Math.floor(index/9) * 9); if(mouseButton==undefined || mouseButton=='Right'){flag(row,col);}else{flip(row,col);}" />
+ </Flipable>
+ </Component>
+ </resources>
+ <Image src="pics/No-Ones-Laughing-3.jpg" tile="true"/>
+ <Description text="Use the 'minehunt' executable to run this demo!" width="300" opacity="{tiles?0:1}" anchors.horizontalCenter="{parent.horizontalCenter}" anchors.verticalCenter="{parent.verticalCenter}"/>
+ <Repeater dataSource="{tiles}" x="1" y="1">
+ <Component>
+ <ComponentInstance component="{tile}"
+ x="{(index - (Math.floor(index/9) * 9)) * 41}"
+ y="{Math.floor(index/9) * 41}"/>
+ </Component>
+ </Repeater>
+ <Item id="gamedata" width="370" height="100" y="380">
+ <Text color="white" font.size="18" x="20" y="20">In play:</Text>
+ <Image x="100" y="20" src="pics/bomb-color.png"/>
+ <Text x="100" y="60" color="white" text="{numMines}"/>
+ <Image x="140" y="20" src="pics/flag-color.png"/>
+ <Text x="140" y="60" color="white" text="{numFlags}"/>
+
+ <Image x="240" y="0" src="{if(isPlaying==true){'pics/smile.png'}else{if(hasWon==true){'pics/glee.png'}else{'pics/frown.png'}}}">
+ <MouseRegion anchors.fill="{parent}" onClicked="reset()"/>
+ </Image>
+ </Item>
+</Item>
diff --git a/examples/declarative/minehunt/pics/No-Ones-Laughing-3.jpg b/examples/declarative/minehunt/pics/No-Ones-Laughing-3.jpg
new file mode 100644
index 0000000..445567f
--- /dev/null
+++ b/examples/declarative/minehunt/pics/No-Ones-Laughing-3.jpg
Binary files differ
diff --git a/examples/declarative/minehunt/pics/bomb-color.png b/examples/declarative/minehunt/pics/bomb-color.png
new file mode 100644
index 0000000..61ad0a9
--- /dev/null
+++ b/examples/declarative/minehunt/pics/bomb-color.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/bomb.png b/examples/declarative/minehunt/pics/bomb.png
new file mode 100644
index 0000000..a992575
--- /dev/null
+++ b/examples/declarative/minehunt/pics/bomb.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/cachepix-black.png b/examples/declarative/minehunt/pics/cachepix-black.png
new file mode 100644
index 0000000..53db3ae
--- /dev/null
+++ b/examples/declarative/minehunt/pics/cachepix-black.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/cachepix-black.sci b/examples/declarative/minehunt/pics/cachepix-black.sci
new file mode 100644
index 0000000..21d5436
--- /dev/null
+++ b/examples/declarative/minehunt/pics/cachepix-black.sci
@@ -0,0 +1,5 @@
+gridLeft: 10
+gridTop: 10
+gridBottom: 10
+gridRight: 10
+imageFile: cachepix-black.png
diff --git a/examples/declarative/minehunt/pics/cachepix-boxless.png b/examples/declarative/minehunt/pics/cachepix-boxless.png
new file mode 100644
index 0000000..288e0e4
--- /dev/null
+++ b/examples/declarative/minehunt/pics/cachepix-boxless.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/cachepix-boxless.sci b/examples/declarative/minehunt/pics/cachepix-boxless.sci
new file mode 100644
index 0000000..d224fd9
--- /dev/null
+++ b/examples/declarative/minehunt/pics/cachepix-boxless.sci
@@ -0,0 +1,5 @@
+gridLeft: 10
+gridTop: 10
+gridBottom: 10
+gridRight: 10
+imageFile: cachepix-boxless.png
diff --git a/examples/declarative/minehunt/pics/flag-color.png b/examples/declarative/minehunt/pics/flag-color.png
new file mode 100644
index 0000000..aadad0f
--- /dev/null
+++ b/examples/declarative/minehunt/pics/flag-color.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/flag.png b/examples/declarative/minehunt/pics/flag.png
new file mode 100644
index 0000000..39cde4d
--- /dev/null
+++ b/examples/declarative/minehunt/pics/flag.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/frown.png b/examples/declarative/minehunt/pics/frown.png
new file mode 100644
index 0000000..52684b3
--- /dev/null
+++ b/examples/declarative/minehunt/pics/frown.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/glee.png b/examples/declarative/minehunt/pics/glee.png
new file mode 100644
index 0000000..59ea583
--- /dev/null
+++ b/examples/declarative/minehunt/pics/glee.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/smile.png b/examples/declarative/minehunt/pics/smile.png
new file mode 100644
index 0000000..ccd52cd
--- /dev/null
+++ b/examples/declarative/minehunt/pics/smile.png
Binary files differ
diff --git a/examples/declarative/minehunt/pics/star.png b/examples/declarative/minehunt/pics/star.png
new file mode 100644
index 0000000..3772359
--- /dev/null
+++ b/examples/declarative/minehunt/pics/star.png
Binary files differ
diff --git a/examples/declarative/mouseregion/mouse.qml b/examples/declarative/mouseregion/mouse.qml
new file mode 100644
index 0000000..f0f22ac
--- /dev/null
+++ b/examples/declarative/mouseregion/mouse.qml
@@ -0,0 +1,24 @@
+<Rect color="white" width="200" height="200">
+ <Rect width="50" height="50" color="red">
+ <Text text="Click" anchors.centeredIn="{parent}"/>
+ <MouseRegion onPressed="print('press (x: ' + x + ' y: ' + y + ')')"
+ onReleased="print('release (x: ' + x + ' y: ' + y + ' isClick: ' + isClick + ' followsPressAndHold: ' + followsPressAndHold + ')')"
+ onClicked="print('click (x: ' + x + ' y: ' + y + ' followsPressAndHold: ' + followsPressAndHold + ')')"
+ onDoubleClicked="print('double click (x: ' + x + ' y: ' + y + ')')"
+ onPressAndHold="print('press and hold')"
+ onExitedWhilePressed="print('exiting while pressed')"
+ onReenteredWhilePressed="print('reentering while pressed')" anchors.fill="{parent}"/>
+ </Rect>
+ <Rect y="100" width="50" height="50" color="blue">
+ <Text text="Drag" anchors.centeredIn="{parent}"/>
+ <MouseRegion drag.target="{parent}"
+ drag.axis="x" drag.xmin="0" drag.xmax="150"
+ onPressed="print('press')"
+ onReleased="print('release (isClick: ' + isClick + ') (followsPressAndHold: ' + followsPressAndHold + ')')"
+ onClicked="print('click' + '(followsPressAndHold: ' + followsPressAndHold + ')')"
+ onDoubleClicked="print('double click')"
+ onPressAndHold="print('press and hold')"
+ onExitedWhilePressed="print('exiting while pressed')"
+ onReenteredWhilePressed="print('reentering while pressed')" anchors.fill="{parent}"/>
+ </Rect>
+</Rect>
diff --git a/examples/declarative/namespaces/BlueStuff/Rect.qml b/examples/declarative/namespaces/BlueStuff/Rect.qml
new file mode 100644
index 0000000..94e066c
--- /dev/null
+++ b/examples/declarative/namespaces/BlueStuff/Rect.qml
@@ -0,0 +1 @@
+<Rect color="blue"/>
diff --git a/examples/declarative/namespaces/Local.qml b/examples/declarative/namespaces/Local.qml
new file mode 100644
index 0000000..5fb2aef
--- /dev/null
+++ b/examples/declarative/namespaces/Local.qml
@@ -0,0 +1 @@
+<Text>This is a local component</Text>
diff --git a/examples/declarative/namespaces/components.qml b/examples/declarative/namespaces/components.qml
new file mode 100644
index 0000000..ea5e2d9
--- /dev/null
+++ b/examples/declarative/namespaces/components.qml
@@ -0,0 +1,17 @@
+<Item id="Root">
+ <properties>
+ <Property name="period" value="1000"/>
+ <Property name="color" value="green"/>
+ </properties>
+
+ <Component id="SpinSquare">
+ <Item>
+ <Rect color="{Root.color}" width="{Root.width}" height="{width}" x="{-width/2}" y="{-height/2}"/>
+ <rotation>
+ <NumericAnimation from="0" to="360" repeat="true" running="true" duration="{Root.period}"/>
+ </rotation>
+ </Item>
+ </Component>
+
+ <ComponentInstance component="{SpinSquare}" x="{Root.width/2}" y="{Root.height/2}"/>
+</Item>
diff --git a/examples/declarative/namespaces/lib/Chronos/Clock.qml b/examples/declarative/namespaces/lib/Chronos/Clock.qml
new file mode 100644
index 0000000..088a45c
--- /dev/null
+++ b/examples/declarative/namespaces/lib/Chronos/Clock.qml
@@ -0,0 +1,15 @@
+<?qtfx namespacepath:http://nokia.com/qml/Chronos=. ?>
+
+<Image id="clock" src="pics/clockface.png" xmlns:This="http://nokia.com/qml/Chronos">
+ <properties>
+ <Property name="hours" value="0"/>
+ <Property name="minutes" value="0"/>
+ <Property name="seconds" value="0"/>
+ </properties>
+ <DateTimeFormatter id="format" time="{clock.time}"/>
+ <Item x="{clock.width/2}" y="{clock.height/2}">
+ <This:Hand id="hour" length="{clock.height/4}" rotation="{clock.hours*30+clock.minutes/2+clock.seconds/120}"/>
+ <This:Hand id="minute" length="{clock.height/3}" thickness="3" rotation="{clock.minutes*6+clock.seconds/10}"/>
+ <This:Hand id="second" length="{clock.height/2.5}" thickness="1" rotation="{clock.seconds*6}"/>
+ </Item>
+</Image>
diff --git a/examples/declarative/namespaces/lib/Chronos/Hand.qml b/examples/declarative/namespaces/lib/Chronos/Hand.qml
new file mode 100644
index 0000000..3662e74
--- /dev/null
+++ b/examples/declarative/namespaces/lib/Chronos/Hand.qml
@@ -0,0 +1,9 @@
+<Item id="Hand">
+ <properties>
+ <Property name="length" value="100"/>
+ <Property name="thickness" value="0"/>
+ </properties>
+ <Item rotation="-90">
+ <Rect width="{length}" height="{thickness==0 ? length/8 : thickness}" y="{-height/2}"/>
+ </Item>
+</Item>
diff --git a/examples/declarative/namespaces/lib/Chronos/pics/clockface.png b/examples/declarative/namespaces/lib/Chronos/pics/clockface.png
new file mode 100644
index 0000000..a885950
--- /dev/null
+++ b/examples/declarative/namespaces/lib/Chronos/pics/clockface.png
Binary files differ
diff --git a/examples/declarative/namespaces/lib/Path/PathLabel.qml b/examples/declarative/namespaces/lib/Path/PathLabel.qml
new file mode 100644
index 0000000..c4b08b0
--- /dev/null
+++ b/examples/declarative/namespaces/lib/Path/PathLabel.qml
@@ -0,0 +1 @@
+<Text color="green"/>
diff --git a/examples/declarative/namespaces/lib/RedStuff/Rect.qml b/examples/declarative/namespaces/lib/RedStuff/Rect.qml
new file mode 100644
index 0000000..3429b09
--- /dev/null
+++ b/examples/declarative/namespaces/lib/RedStuff/Rect.qml
@@ -0,0 +1 @@
+<Rect color="red"/>
diff --git a/examples/declarative/namespaces/lib/Wrong/Wrong.qml b/examples/declarative/namespaces/lib/Wrong/Wrong.qml
new file mode 100644
index 0000000..3af55f6
--- /dev/null
+++ b/examples/declarative/namespaces/lib/Wrong/Wrong.qml
@@ -0,0 +1,3 @@
+<Rect>
+ <Local/> <!-- not allowed - not in this component! -->
+</Rect>
diff --git a/examples/declarative/namespaces/library.qml b/examples/declarative/namespaces/library.qml
new file mode 100644
index 0000000..ae10ed8
--- /dev/null
+++ b/examples/declarative/namespaces/library.qml
@@ -0,0 +1,12 @@
+<?qtfx namespacepath:http://nokia.com/qml=lib ?>
+
+<Rect id="obj" width="200" height="200" xmlns:Chronos="http://nokia.com/qml/Chronos">
+ <properties>
+ <Property name="time_sec"/>
+ </properties>
+ <time_sec> <!-- simple animation, not bound to the real time -->
+ <NumericAnimation from="0" to="43200" duration="43200000" running="true" repeat="true"/>
+ </time_sec>
+ <Chronos:Clock x="10" y="10" width="{parent.width-20}" height="{parent.height-20}"
+ hours="{Math.floor(time_sec/3600)}" minutes="{Math.floor(time_sec/60)%60}" seconds="{time_sec%60}"/>
+</Rect>
diff --git a/examples/declarative/namespaces/path.qml b/examples/declarative/namespaces/path.qml
new file mode 100644
index 0000000..795447b
--- /dev/null
+++ b/examples/declarative/namespaces/path.qml
@@ -0,0 +1,18 @@
+<!-- Empty Namespaces paths allow unqualified Types to be found
+ in other locations. For file URLs, multiple paths can be
+ given, forming a file search path. -->
+
+<?qtfx namespacepath:=lib/Chronos ?> <!-- Clock will be found here -->
+<?qtfx namespacepath:=lib/Path ?> <!-- PathLabel will be found here -->
+
+<Rect id="obj" width="200" height="200">
+ <properties>
+ <Property name="time_sec"/>
+ </properties>
+ <time_sec> <!-- simple animation, not bound to the real time -->
+ <NumericAnimation from="0" to="43200" duration="43200000" running="true" repeat="true"/>
+ </time_sec>
+ <Clock x="10" y="10" width="{parent.width-20}" height="{parent.height-20}"
+ hours="{Math.floor(time_sec/3600)}" minutes="{Math.floor(time_sec/60)%60}" seconds="{time_sec%60}"/>
+ <PathLabel text="This is a clock"/>
+</Rect>
diff --git a/examples/declarative/namespaces/simple.qml b/examples/declarative/namespaces/simple.qml
new file mode 100644
index 0000000..16d9815
--- /dev/null
+++ b/examples/declarative/namespaces/simple.qml
@@ -0,0 +1,5 @@
+<?qtfx namespacepath:http://nokia.com/qml=lib ?>
+<Rect id="obj" width="100" height="100" xmlns:bs="BlueStuff" xmlns:rs="http://nokia.com/qml/RedStuff">
+ <bs:Rect x="20" y="20" width="50" height="50"/>
+ <rs:Rect x="30" y="30" width="50" height="50"/>
+</Rect>
diff --git a/examples/declarative/namespaces/wrong1.qml b/examples/declarative/namespaces/wrong1.qml
new file mode 100644
index 0000000..721c45a
--- /dev/null
+++ b/examples/declarative/namespaces/wrong1.qml
@@ -0,0 +1,4 @@
+<?qtfx namespacepath:http://nokia.com/qml=lib ?>
+<Rect id="obj" width="100" height="100" xmlns:w="http://nokia.com/qml/Wrong" color="white">
+ <w:Wrong/>
+</Rect>
diff --git a/examples/declarative/scrollbar/ScrollBar.qml b/examples/declarative/scrollbar/ScrollBar.qml
new file mode 100644
index 0000000..470a170
--- /dev/null
+++ b/examples/declarative/scrollbar/ScrollBar.qml
@@ -0,0 +1,26 @@
+<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'
+ -->
+ <properties>
+ <Property name="position"/>
+ <Property name="pageSize"/>
+ <Property name="orientation" value="Vertical"/>
+ </properties>
+
+ <!-- A light, semi-transparent background -->
+ <Rect id="Background" radius="{orientation == 'Vertical' ? (width/2) : (height/2)}" color="white" opacity="0.3" anchors.fill="{parent}"/>
+
+ <!-- Size the bar to the required size, depending upon the orientation. -->
+ <Rect opacity="0.6" color="black"
+ radius="{orientation == 'Vertical' ? (width/2) : (height/2)}"
+ x="{orientation == 'Vertical' ? 2 : (ScrollBar.position * (ScrollBar.width-4) + 2)}"
+ y="{orientation == 'Vertical' ? (ScrollBar.position * (ScrollBar.height-4) + 2) : 2}"
+ width="{orientation == 'Vertical' ? (parent.width-4) : (ScrollBar.pageSize * (ScrollBar.width-4))}"
+ height="{orientation == 'Vertical' ? (ScrollBar.pageSize * (ScrollBar.height-4)) : (parent.height-4)}"
+ />
+</Item>
diff --git a/examples/declarative/scrollbar/display.qml b/examples/declarative/scrollbar/display.qml
new file mode 100644
index 0000000..697b68a
--- /dev/null
+++ b/examples/declarative/scrollbar/display.qml
@@ -0,0 +1,28 @@
+<Rect width="640" height="480">
+
+ <!-- Create a flickable to view a large image. -->
+ <Flickable id="View" anchors.fill="{parent}">
+ <Image id="Picture" src="pics/niagara_falls.jpg"/>
+ <viewportWidth>{Picture.width}</viewportWidth>
+ <viewportHeight>{Picture.height}</viewportHeight>
+
+ <!-- Only show the scrollbars when the view is moving. -->
+ <states>
+ <State name="ShowBars" when="{View.moving}">
+ <SetProperty target="{SBV}" property="opacity" value="1" />
+ <SetProperty target="{SBH}" property="opacity" value="1" />
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="*">
+ <NumericAnimation properties="opacity" duration="400"/>
+ </Transition>
+ </transitions>
+
+ </Flickable>
+
+ <!-- Attach scrollbars to the right and bottom edges of the view. -->
+ <ScrollBar id="SBV" opacity="0" orientation="Vertical" position="{View.pageYPosition}" pageSize="{View.pageHeight}" width="12" height="{View.height-12}" anchors.right="{View.right}"/>
+ <ScrollBar id="SBH" opacity="0" orientation="Horizontal" position="{View.pageXPosition}" pageSize="{View.pageWidth}" height="12" width="{View.width-12}" anchors.bottom="{View.bottom}"/>
+
+</Rect>
diff --git a/examples/declarative/scrollbar/pics/niagara_falls.jpg b/examples/declarative/scrollbar/pics/niagara_falls.jpg
new file mode 100644
index 0000000..618d808
--- /dev/null
+++ b/examples/declarative/scrollbar/pics/niagara_falls.jpg
Binary files differ
diff --git a/examples/declarative/slideswitch/Switch.qml b/examples/declarative/slideswitch/Switch.qml
new file mode 100644
index 0000000..90e6e64
--- /dev/null
+++ b/examples/declarative/slideswitch/Switch.qml
@@ -0,0 +1,52 @@
+<Item id="Switch" width="{Groove.width}" height="{Groove.height}">
+ <properties><Property name="on"/></properties>
+ <Script>
+ function toggle() {
+ if(Switch.state == "On")
+ Switch.state = "Off";
+ else
+ Switch.state = "On";
+ }
+ function dorelease() {
+ print(Knob.x);
+ if(Knob.x == 1) {
+ if(Switch.state == "Off")
+ return;
+ }
+
+ if(Knob.x == 78) {
+ if(Switch.state == "On")
+ return;
+ }
+
+ toggle();
+ }
+ </Script>
+ <Image id="Groove" src="background.svg"/>
+ <MouseRegion anchors.fill="{Groove}" onClicked="toggle()"/>
+ <Image id="Knob" src="knob.svg" x="1" y="2"/>
+ <MouseRegion anchors.fill="{Knob}"
+ onClicked="toggle()"
+ onReleased="if (!isClick) dorelease()"
+ drag.target="{Knob}"
+ drag.axis="x"
+ drag.xmin="1"
+ drag.xmax="78"/>
+
+ <states>
+ <State name="On">
+ <SetProperty target="{Knob}" property="x" value="78" />
+ <SetProperty target="{Switch}" property="on" value="true" />
+ </State>
+ <State name="Off">
+ <SetProperty target="{Knob}" property="x" value="1" />
+ <SetProperty target="{Switch}" property="on" value="false" />
+ </State>
+ </states>
+
+ <transitions>
+ <Transition>
+ <NumericAnimation properties="x" easing="easeInOutQuad" duration="200"/>
+ </Transition>
+ </transitions>
+</Item>
diff --git a/examples/declarative/slideswitch/background.svg b/examples/declarative/slideswitch/background.svg
new file mode 100644
index 0000000..f920d3e
--- /dev/null
+++ b/examples/declarative/slideswitch/background.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="130px" height="56px" viewBox="0 0 130 56" enable-background="new 0 0 130 56" xml:space="preserve">
+<defs>
+</defs>
+<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-37.5005" y1="-66" x2="-37.5005" y2="-121.9985" gradientTransform="matrix(1 0 0 -1 102.5 -66)">
+ <stop offset="0.0056" style="stop-color:#000000"/>
+ <stop offset="1" style="stop-color:#EAECEF"/>
+</linearGradient>
+<path fill="url(#SVGID_1_)" d="M101.998,55.998H28c-15.439,0-28-12.562-28-28C0,12.56,12.561,0,28,0h73.998
+ c15.439,0,28,12.559,28,27.998C129.998,43.438,117.438,55.998,101.998,55.998L101.998,55.998z"/>
+<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-5.5" y1="-132.1338" x2="-69.5002" y2="-55.8613" gradientTransform="matrix(1 0 0 -1 102.5 -66)">
+ <stop offset="0.0056" style="stop-color:#000000"/>
+ <stop offset="1" style="stop-color:#828385"/>
+</linearGradient>
+<path fill="url(#SVGID_2_)" d="M127.999,27.998c0,14.359-11.642,26-26,26h-74c-14.359,0-26-11.641-26-26l0,0
+ c0-14.359,11.641-26,26-26h74C116.357,1.998,127.999,13.639,127.999,27.998L127.999,27.998z"/>
+</svg>
diff --git a/examples/declarative/slideswitch/display.qml b/examples/declarative/slideswitch/display.qml
new file mode 100644
index 0000000..b62422c
--- /dev/null
+++ b/examples/declarative/slideswitch/display.qml
@@ -0,0 +1,3 @@
+<Rect color="white" width="150" height="150">
+ <Switch anchors.centeredIn="{parent}"/>
+</Rect>
diff --git a/examples/declarative/slideswitch/knob.svg b/examples/declarative/slideswitch/knob.svg
new file mode 100644
index 0000000..fb69337
--- /dev/null
+++ b/examples/declarative/slideswitch/knob.svg
@@ -0,0 +1,867 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ 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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ x="0px"
+ y="0px"
+ width="52px"
+ height="52px"
+ viewBox="0 0 52 52"
+ enable-background="new 0 0 52 52"
+ xml:space="preserve"
+ id="svg3883"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docname="knob_on.svg"
+ sodipodi:docbase="/local/axel/embeddedwidgets/embeddedstories/skins/svgslideswitch/MetallicBrush"><metadata
+ id="metadata4200"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+ inkscape:window-height="640"
+ inkscape:window-width="937"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="8.3653846"
+ inkscape:cx="26.000002"
+ inkscape:cy="26"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="svg3883" />
+<defs
+ id="defs3885">
+</defs>
+<linearGradient
+ id="SVGID_1_"
+ gradientUnits="userSpaceOnUse"
+ x1="-59.7866"
+ y1="-115.917"
+ x2="-93.2123"
+ y2="-76.0818"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#000000"
+ id="stop3888" />
+ <stop
+ offset="1"
+ style="stop-color:#EAECEF"
+ id="stop3890" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="26"
+ id="circle3892"
+ style="fill:url(#SVGID_1_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="26"
+ sodipodi:ry="26"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_2_"
+ gradientUnits="userSpaceOnUse"
+ x1="-100.5"
+ y1="-96"
+ x2="-52.5"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3895" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3897" />
+ <stop
+ offset="0.6043"
+ style="stop-color:#E7EAED"
+ id="stop3899" />
+ <stop
+ offset="0.6751"
+ style="stop-color:#DEE4E7"
+ id="stop3901" />
+ <stop
+ offset="0.7358"
+ style="stop-color:#CFD9DD"
+ id="stop3903" />
+ <stop
+ offset="0.791"
+ style="stop-color:#B9CACF"
+ id="stop3905" />
+ <stop
+ offset="0.8425"
+ style="stop-color:#9EB6BD"
+ id="stop3907" />
+ <stop
+ offset="0.891"
+ style="stop-color:#7B9EA7"
+ id="stop3909" />
+ <stop
+ offset="0.9374"
+ style="stop-color:#53828C"
+ id="stop3911" />
+ <stop
+ offset="0.9809"
+ style="stop-color:#25626E"
+ id="stop3913" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3915" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="24"
+ id="circle3917"
+ style="fill:url(#SVGID_2_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="24"
+ sodipodi:ry="24"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_3_"
+ gradientUnits="userSpaceOnUse"
+ x1="-98.6328"
+ y1="-96"
+ x2="-54.3672"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3920" />
+ <stop
+ offset="0.073"
+ style="stop-color:#8FAECB"
+ id="stop3922" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3924" />
+ <stop
+ offset="0.5902"
+ style="stop-color:#E7E9ED"
+ id="stop3926" />
+ <stop
+ offset="0.618"
+ style="stop-color:#E4E7EB"
+ id="stop3928" />
+ <stop
+ offset="0.6697"
+ style="stop-color:#E0E4E9"
+ id="stop3930" />
+ <stop
+ offset="0.7211"
+ style="stop-color:#D4DCE1"
+ id="stop3932" />
+ <stop
+ offset="0.7722"
+ style="stop-color:#C0CFD5"
+ id="stop3934" />
+ <stop
+ offset="0.809"
+ style="stop-color:#ADC2C9"
+ id="stop3936" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3938" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="22.132999"
+ id="circle3940"
+ style="fill:url(#SVGID_3_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="22.132999"
+ sodipodi:ry="22.132999"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_4_"
+ gradientUnits="userSpaceOnUse"
+ x1="-96.7671"
+ y1="-96"
+ x2="-56.2324"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3943" />
+ <stop
+ offset="0.073"
+ style="stop-color:#86A7C4"
+ id="stop3945" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3947" />
+ <stop
+ offset="0.577"
+ style="stop-color:#E7EAED"
+ id="stop3949" />
+ <stop
+ offset="0.618"
+ style="stop-color:#E1E6EA"
+ id="stop3951" />
+ <stop
+ offset="0.6697"
+ style="stop-color:#DDE3E8"
+ id="stop3953" />
+ <stop
+ offset="0.7211"
+ style="stop-color:#D1DBE1"
+ id="stop3955" />
+ <stop
+ offset="0.7722"
+ style="stop-color:#BDCDD5"
+ id="stop3957" />
+ <stop
+ offset="0.809"
+ style="stop-color:#AAC0CA"
+ id="stop3959" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3961" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="20.267"
+ id="circle3963"
+ style="fill:url(#SVGID_4_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="20.267"
+ sodipodi:ry="20.267"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_5_"
+ gradientUnits="userSpaceOnUse"
+ x1="-94.8999"
+ y1="-96"
+ x2="-58.0996"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3966" />
+ <stop
+ offset="0.073"
+ style="stop-color:#7E9FBC"
+ id="stop3968" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3970" />
+ <stop
+ offset="0.5709"
+ style="stop-color:#E6E9ED"
+ id="stop3972" />
+ <stop
+ offset="0.618"
+ style="stop-color:#DFE4E9"
+ id="stop3974" />
+ <stop
+ offset="0.6687"
+ style="stop-color:#DBE1E7"
+ id="stop3976" />
+ <stop
+ offset="0.7193"
+ style="stop-color:#CFD9E0"
+ id="stop3978" />
+ <stop
+ offset="0.7695"
+ style="stop-color:#BBCCD6"
+ id="stop3980" />
+ <stop
+ offset="0.809"
+ style="stop-color:#A6BECA"
+ id="stop3982" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3984" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="18.4"
+ id="circle3986"
+ style="fill:url(#SVGID_5_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="18.4"
+ sodipodi:ry="18.4"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_6_"
+ gradientUnits="userSpaceOnUse"
+ x1="-93.0332"
+ y1="-96"
+ x2="-59.9668"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3989" />
+ <stop
+ offset="0.073"
+ style="stop-color:#7697B4"
+ id="stop3991" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3993" />
+ <stop
+ offset="0.5636"
+ style="stop-color:#E6E9ED"
+ id="stop3995" />
+ <stop
+ offset="0.618"
+ style="stop-color:#DCE2E8"
+ id="stop3997" />
+ <stop
+ offset="0.6687"
+ style="stop-color:#D8DFE6"
+ id="stop3999" />
+ <stop
+ offset="0.7193"
+ style="stop-color:#CCD7E0"
+ id="stop4001" />
+ <stop
+ offset="0.7695"
+ style="stop-color:#B8CAD5"
+ id="stop4003" />
+ <stop
+ offset="0.809"
+ style="stop-color:#A3BCCA"
+ id="stop4005" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4007" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="16.533001"
+ id="circle4009"
+ style="fill:url(#SVGID_6_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="16.533001"
+ sodipodi:ry="16.533001"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_7_"
+ gradientUnits="userSpaceOnUse"
+ x1="-91.167"
+ y1="-96"
+ x2="-61.833"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4012" />
+ <stop
+ offset="0.073"
+ style="stop-color:#6D8FAD"
+ id="stop4014" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4016" />
+ <stop
+ offset="0.5605"
+ style="stop-color:#E5E8EC"
+ id="stop4018" />
+ <stop
+ offset="0.618"
+ style="stop-color:#DAE1E7"
+ id="stop4020" />
+ <stop
+ offset="0.6679"
+ style="stop-color:#D6DEE5"
+ id="stop4022" />
+ <stop
+ offset="0.7175"
+ style="stop-color:#CAD6DF"
+ id="stop4024" />
+ <stop
+ offset="0.7669"
+ style="stop-color:#B6C9D6"
+ id="stop4026" />
+ <stop
+ offset="0.809"
+ style="stop-color:#9FBACB"
+ id="stop4028" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4030" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="14.667"
+ id="circle4032"
+ style="fill:url(#SVGID_7_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="14.667"
+ sodipodi:ry="14.667"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_8_"
+ gradientUnits="userSpaceOnUse"
+ x1="-89.2998"
+ y1="-96"
+ x2="-63.7002"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4035" />
+ <stop
+ offset="0.073"
+ style="stop-color:#6587A5"
+ id="stop4037" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4039" />
+ <stop
+ offset="0.5588"
+ style="stop-color:#E4E8EC"
+ id="stop4041" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D8DFE7"
+ id="stop4043" />
+ <stop
+ offset="0.6675"
+ style="stop-color:#D4DCE5"
+ id="stop4045" />
+ <stop
+ offset="0.7167"
+ style="stop-color:#C8D5E0"
+ id="stop4047" />
+ <stop
+ offset="0.7657"
+ style="stop-color:#B4C8D6"
+ id="stop4049" />
+ <stop
+ offset="0.809"
+ style="stop-color:#9CB8CB"
+ id="stop4051" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4053" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="12.8"
+ id="circle4055"
+ style="fill:url(#SVGID_8_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="12.8"
+ sodipodi:ry="12.8"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_9_"
+ gradientUnits="userSpaceOnUse"
+ x1="-87.4331"
+ y1="-96"
+ x2="-65.5664"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4058" />
+ <stop
+ offset="0.073"
+ style="stop-color:#5D809D"
+ id="stop4060" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4062" />
+ <stop
+ offset="0.5567"
+ style="stop-color:#E3E7EC"
+ id="stop4064" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D5DDE6"
+ id="stop4066" />
+ <stop
+ offset="0.6671"
+ style="stop-color:#D1DAE4"
+ id="stop4068" />
+ <stop
+ offset="0.7159"
+ style="stop-color:#C5D3DF"
+ id="stop4070" />
+ <stop
+ offset="0.7645"
+ style="stop-color:#B1C6D6"
+ id="stop4072" />
+ <stop
+ offset="0.809"
+ style="stop-color:#98B5CB"
+ id="stop4074" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4076" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="10.933"
+ id="circle4078"
+ style="fill:url(#SVGID_9_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="10.933"
+ sodipodi:ry="10.933"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_10_"
+ gradientUnits="userSpaceOnUse"
+ x1="-85.5659"
+ y1="-96"
+ x2="-67.4336"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4081" />
+ <stop
+ offset="0.073"
+ style="stop-color:#547896"
+ id="stop4083" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4085" />
+ <stop
+ offset="0.5588"
+ style="stop-color:#E1E6EB"
+ id="stop4087" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D3DCE5"
+ id="stop4089" />
+ <stop
+ offset="0.6663"
+ style="stop-color:#CFD9E3"
+ id="stop4091" />
+ <stop
+ offset="0.7143"
+ style="stop-color:#C3D2DF"
+ id="stop4093" />
+ <stop
+ offset="0.7621"
+ style="stop-color:#AFC5D7"
+ id="stop4095" />
+ <stop
+ offset="0.809"
+ style="stop-color:#94B3CC"
+ id="stop4097" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4099" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="9.066"
+ id="circle4101"
+ style="fill:url(#SVGID_10_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="9.066"
+ sodipodi:ry="9.066"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_11_"
+ gradientUnits="userSpaceOnUse"
+ x1="-83.7002"
+ y1="-96"
+ x2="-69.2998"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4104" />
+ <stop
+ offset="0.073"
+ style="stop-color:#4C708E"
+ id="stop4106" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4108" />
+ <stop
+ offset="0.5625"
+ style="stop-color:#DEE4EA"
+ id="stop4110" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D0DAE4"
+ id="stop4112" />
+ <stop
+ offset="0.6663"
+ style="stop-color:#CCD7E2"
+ id="stop4114" />
+ <stop
+ offset="0.7143"
+ style="stop-color:#C0D0DE"
+ id="stop4116" />
+ <stop
+ offset="0.7621"
+ style="stop-color:#ACC3D6"
+ id="stop4118" />
+ <stop
+ offset="0.809"
+ style="stop-color:#91B1CC"
+ id="stop4120" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4122" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="7.1999998"
+ id="circle4124"
+ style="fill:url(#SVGID_11_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="7.1999998"
+ sodipodi:ry="7.1999998"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_12_"
+ gradientUnits="userSpaceOnUse"
+ x1="-81.833"
+ y1="-96"
+ x2="-71.167"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4127" />
+ <stop
+ offset="0.073"
+ style="stop-color:#446986"
+ id="stop4129" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4131" />
+ <stop
+ offset="0.5757"
+ style="stop-color:#D9E0E8"
+ id="stop4133" />
+ <stop
+ offset="0.618"
+ style="stop-color:#CED8E3"
+ id="stop4135" />
+ <stop
+ offset="0.6655"
+ style="stop-color:#CAD5E2"
+ id="stop4137" />
+ <stop
+ offset="0.7129"
+ style="stop-color:#BECEDD"
+ id="stop4139" />
+ <stop
+ offset="0.7601"
+ style="stop-color:#AAC1D6"
+ id="stop4141" />
+ <stop
+ offset="0.807"
+ style="stop-color:#8EB0CC"
+ id="stop4143" />
+ <stop
+ offset="0.809"
+ style="stop-color:#8DAFCC"
+ id="stop4145" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4147" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="5.3330002"
+ id="circle4149"
+ style="fill:url(#SVGID_12_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="5.3330002"
+ sodipodi:ry="5.3330002"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_13_"
+ gradientUnits="userSpaceOnUse"
+ x1="-79.9658"
+ y1="-96"
+ x2="-73.0342"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4152" />
+ <stop
+ offset="0.073"
+ style="stop-color:#3B617F"
+ id="stop4154" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4156" />
+ <stop
+ offset="0.6087"
+ style="stop-color:#CED9E3"
+ id="stop4158" />
+ <stop
+ offset="0.618"
+ style="stop-color:#CBD7E2"
+ id="stop4160" />
+ <stop
+ offset="0.6655"
+ style="stop-color:#C7D4E1"
+ id="stop4162" />
+ <stop
+ offset="0.7129"
+ style="stop-color:#BBCDDD"
+ id="stop4164" />
+ <stop
+ offset="0.7601"
+ style="stop-color:#A7C0D6"
+ id="stop4166" />
+ <stop
+ offset="0.807"
+ style="stop-color:#8BAECD"
+ id="stop4168" />
+ <stop
+ offset="0.809"
+ style="stop-color:#8AADCD"
+ id="stop4170" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4172" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="3.4660001"
+ id="circle4174"
+ style="fill:url(#SVGID_13_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="3.4660001"
+ sodipodi:ry="3.4660001"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_14_"
+ gradientUnits="userSpaceOnUse"
+ x1="-78.1001"
+ y1="-96"
+ x2="-74.9004"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4177" />
+ <stop
+ offset="0.073"
+ style="stop-color:#335977"
+ id="stop4179" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4181" />
+ <stop
+ offset="0.618"
+ style="stop-color:#C9D5E1"
+ id="stop4183" />
+ <stop
+ offset="0.6648"
+ style="stop-color:#C5D3E0"
+ id="stop4185" />
+ <stop
+ offset="0.7114"
+ style="stop-color:#B9CBDC"
+ id="stop4187" />
+ <stop
+ offset="0.758"
+ style="stop-color:#A5BFD6"
+ id="stop4189" />
+ <stop
+ offset="0.8042"
+ style="stop-color:#89ADCE"
+ id="stop4191" />
+ <stop
+ offset="0.809"
+ style="stop-color:#86ABCD"
+ id="stop4193" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4195" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="1.6"
+ id="circle4197"
+ style="fill:url(#SVGID_14_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="1.6"
+ sodipodi:ry="1.6"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+</svg> \ No newline at end of file
diff --git a/examples/declarative/states/states.qml b/examples/declarative/states/states.qml
new file mode 100644
index 0000000..e540d25
--- /dev/null
+++ b/examples/declarative/states/states.qml
@@ -0,0 +1,40 @@
+<Rect id="Page" width="300" height="300" color="white">
+
+ <!-- A target region. Clicking in here sets the state to '' - the default state -->
+ <Rect width="50" height="50" x="0" y="0" color="transparent" pen.color="black">
+ <MouseRegion anchors.fill="{parent}" onClicked="Page.state=''"/>
+ </Rect>
+
+ <!-- Another target region. Clicking in here sets the state to 'Position1' -->
+ <Rect width="50" height="50" x="150" y="50" color="transparent" pen.color="black">
+ <MouseRegion anchors.fill="{parent}" onClicked="Page.state='Position1'"/>
+ </Rect>
+
+ <!-- Another target region. Clicking in here sets the state to 'Position2' -->
+ <Rect width="50" height="50" x="0" y="200" color="transparent" pen.color="black">
+ <MouseRegion anchors.fill="{parent}" onClicked="Page.state='Position2'"/>
+ </Rect>
+
+ <!-- Rect which will be moved when my state changes -->
+ <Rect id="myrect" width="50" height="50" color="red"/>
+
+ <states>
+
+ <!-- In state 'Position1', change the 'myrect' item x, y to 150, 50. -->
+ <State name="Position1">
+ <SetProperty target="{myrect}" property="x" value="150"/>
+ <SetProperty target="{myrect}" property="y" value="50"/>
+ </State>
+
+ <!--
+ In state 'Position2', change y to 100. We do not specify 'x' here -
+ it will therefore be restored to its default value of 0, if it
+ had been changed.
+ -->
+ <State name="Position2">
+ <SetProperty target="{myrect}" property="y" value="200"/>
+ </State>
+
+ </states>
+
+</Rect>
diff --git a/examples/declarative/states/transitions.qml b/examples/declarative/states/transitions.qml
new file mode 100644
index 0000000..c3f3515
--- /dev/null
+++ b/examples/declarative/states/transitions.qml
@@ -0,0 +1,68 @@
+<Rect id="Page" width="300" height="300" color="white">
+
+ <!-- A target region. Clicking in here sets the state to '' - the default state -->
+ <Rect width="50" height="50" x="0" y="0" color="transparent" pen.color="black">
+ <MouseRegion anchors.fill="{parent}" onClicked="Page.state=''"/>
+ </Rect>
+
+ <!-- Another target region. Clicking in here sets the state to 'Position1' -->
+ <Rect width="50" height="50" x="150" y="50" color="transparent" pen.color="black">
+ <MouseRegion anchors.fill="{parent}" onClicked="Page.state='Position1'"/>
+ </Rect>
+
+ <!-- Another target region. Clicking in here sets the state to 'Position2' -->
+ <Rect width="50" height="50" x="0" y="200" color="transparent" pen.color="black">
+ <MouseRegion anchors.fill="{parent}" onClicked="Page.state='Position2'"/>
+ </Rect>
+
+ <!-- Rect which will be moved when my state changes -->
+ <Rect id="myrect" width="50" height="50" color="red"/>
+
+ <states>
+
+ <!-- In state 'Position1', change the 'myrect' item x, y to 150, 50. -->
+ <State name="Position1">
+ <SetProperty target="{myrect}" property="x" value="150"/>
+ <SetProperty target="{myrect}" property="y" value="50"/>
+ </State>
+
+ <!--
+ In state 'Position2', change y to 100. We do not specify 'x' here -
+ it will therefore be restored to its default value of 0, if it
+ had been changed.
+ -->
+ <State name="Position2">
+ <SetProperty target="{myrect}" property="y" value="200"/>
+ </State>
+
+ </states>
+
+ <!-- transitions define how the properties change. -->
+ <transitions>
+
+ <!--
+ When transitioning to 'Position1' move x,y over a duration of 1 second,
+ with easeOutBounce easing function.
+ -->
+ <Transition fromState="*" toState="Position1">
+ <NumericAnimation properties="x,y" easing="easeOutBounce" duration="1000" />
+ </Transition>
+
+ <!--
+ When transitioning to 'Position2' move x,y over a duration of 2 seconds,
+ with easeInOutQuad easing function.
+ -->
+ <Transition fromState="*" toState="Position2">
+ <NumericAnimation properties="x,y" easing="easeInOutQuad" duration="2000" />
+ </Transition>
+
+ <!--
+ For any other state changes move x,y linearly over duration of 200ms.
+ -->
+ <Transition>
+ <NumericAnimation properties="x,y" duration="200" />
+ </Transition>
+
+ </transitions>
+
+</Rect>
diff --git a/examples/declarative/support/contact.cpp b/examples/declarative/support/contact.cpp
new file mode 100644
index 0000000..7d90fc4
--- /dev/null
+++ b/examples/declarative/support/contact.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved.
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "contact.h"
+#include "qmltypes.h"
+
+QML_DEFINE_TYPE(Contact,Contact);
+Contact::Contact() : QObject(0)
+{
+ m_firstName = "John";
+ m_lastName = "Smith";
+ m_portraitFile = "contact.png";
+ m_company = "Trollkia";
+ m_emails << "smith@trollkia.com" << "john45@gmail.com";
+
+ m_numbers << new PhoneNumber;
+ m_numbers << new PhoneNumber;
+ m_numbers << new PhoneNumber;
+
+ m_numbers.at(0)->setType(PhoneNumber::HomePhone);
+ m_numbers.at(0)->setNumber("35412451");
+
+ m_numbers.at(1)->setType(PhoneNumber::BusinessPhone);
+ m_numbers.at(1)->setNumber("33424994");
+
+ m_numbers.at(2)->setType(PhoneNumber::MobilePhone);
+ m_numbers.at(2)->setNumber("0424655137");
+
+ m_addresses << new Address;
+ m_addresses << new Address;
+ m_addresses << new Address;
+ m_addresses.at(0)->setNumber(13);
+ m_addresses.at(0)->setStreet("Blackhill Cr");
+ m_addresses.at(0)->setCountry("Australia");
+ m_addresses.at(1)->setNumber(116);
+ m_addresses.at(1)->setStreet("Sandankerveien");
+ m_addresses.at(1)->setCountry("Norway");
+ m_addresses.at(2)->setNumber(92);
+ m_addresses.at(2)->setStreet("Elizibeth St");
+ m_addresses.at(2)->setCountry("Australia");
+}
+
+void Contact::addNumber(PhoneNumber *newNumber)
+{
+
+ m_numbers << newNumber;
+ emit numbersChanged();
+}
+
+void Contact::addAddress(Address *newAddress)
+{
+ m_addresses << newAddress;
+ emit addressesChanged();
+}
+
+void Contact::addEmail(QString &newEmail)
+{
+
+ m_emails << newEmail;
+ emit emailsChanged();
+}
+
+QML_DEFINE_TYPE(Address,Address);
+Address::Address()
+: _number(0)
+{
+}
+
+QML_DEFINE_TYPE(PhoneNumber, PhoneNumber);
+PhoneNumber::PhoneNumber()
+: _type(HomePhone)
+{
+}
diff --git a/examples/declarative/support/contact.h b/examples/declarative/support/contact.h
new file mode 100644
index 0000000..c403f8b
--- /dev/null
+++ b/examples/declarative/support/contact.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved.
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef CONTACT_H
+#define CONTACT_H
+
+#include <qml.h>
+#include <QtGui>
+
+
+class Address : public QObject
+{
+ Q_OBJECT
+public:
+ Address();
+
+ Q_PROPERTY(int number READ number WRITE setNumber NOTIFY changed);
+ Q_PROPERTY(QString street READ street WRITE setStreet NOTIFY changed);
+ Q_PROPERTY(QString country READ country WRITE setCountry NOTIFY changed);
+
+ int number() const { return _number; }
+ void setNumber(int n) { _number = n; emit changed(); }
+
+ QString street() const { return _street; }
+ void setStreet(const QString &s) { _street = s; emit changed(); }
+
+ QString country() const { return _country; }
+ void setCountry(const QString &c) { _country = c; emit changed(); }
+
+signals:
+ void changed();
+
+private:
+ int _number;
+ QString _street;
+ QString _country;
+};
+QML_DECLARE_TYPE(Address);
+
+class PhoneNumber : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(PhoneType)
+public:
+ PhoneNumber();
+
+ enum PhoneType {
+ HomePhone,
+ BusinessPhone,
+ MobilePhone
+ };
+
+ Q_PROPERTY(QString number READ number WRITE setNumber NOTIFY changed);
+ Q_PROPERTY(PhoneType type READ type WRITE setType NOTIFY changed);
+
+ QString number() const { return _number; }
+ void setNumber(QString n) { _number = n; emit changed(); }
+
+ PhoneType type() const { return _type; }
+ void setType(PhoneType type) { _type = type; emit changed(); }
+
+signals:
+ void changed();
+
+private:
+ QString _number;
+ PhoneType _type;
+};
+QML_DECLARE_TYPE(PhoneNumber);
+
+class Contact : public QObject
+{
+ Q_OBJECT
+public:
+ Contact();
+
+ Q_PROPERTY(QString firstName READ firstName WRITE setFirstName NOTIFY nameChanged);
+ QString firstName() const { return m_firstName; }
+
+ Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY nameChanged);
+ QString lastName() const { return m_lastName; }
+
+ Q_PROPERTY(QString portraitFile READ portraitFile WRITE setPortraitFile NOTIFY portraitChanged);
+ QString portraitFile() const { return m_portraitFile; }
+
+ Q_PROPERTY(QString company READ company WRITE setCompany NOTIFY companyChanged);
+ QString company() const { return m_company; }
+
+ Q_PROPERTY(QStringList emails READ emails WRITE setEmails NOTIFY emailsChanged);
+ QStringList emails() const { return m_emails; }
+
+ Q_PROPERTY(QList<Address *>* addresses READ addresses);
+ QList<Address *>* addresses() { return &m_addresses; }
+
+ Q_PROPERTY(QList<PhoneNumber *>* numbers READ numbers);
+ QList<PhoneNumber *>* numbers() { return &m_numbers; }
+
+
+ void addEmail(QString&);
+ void addAddress(Address*);
+ void addNumber(PhoneNumber*);
+
+public slots:
+ void setFirstName(const QString &name) { m_firstName = name; emit nameChanged(); }
+ void setLastName(const QString &name) { m_lastName = name; emit nameChanged(); }
+ void setPortraitFile(const QString &portraitFile) { m_portraitFile = portraitFile; emit portraitChanged(); }
+ void setCompany(const QString &company) { m_company = company; emit companyChanged(); }
+ void setEmails(const QStringList &emails) { m_emails = emails; emit emailsChanged(); }
+
+signals:
+ void nameChanged();
+ void portraitChanged();
+ void companyChanged();
+ void emailsChanged();
+ void numbersChanged();
+ void addressesChanged();
+
+private:
+ QString m_firstName;
+ QString m_lastName;
+ QString m_portraitFile;
+
+ QString m_company;
+
+ QList<Address *> m_addresses;
+ QList<PhoneNumber *>m_numbers;
+ QStringList m_emails;
+};
+QML_DECLARE_TYPE(Contact);
+
+#endif
diff --git a/examples/declarative/support/contactmodel.cpp b/examples/declarative/support/contactmodel.cpp
new file mode 100644
index 0000000..efe108fb
--- /dev/null
+++ b/examples/declarative/support/contactmodel.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved.
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "contactmodel.h"
+#include "qmltypes.h"
+
+ContactModel::ContactModel(QObject *parent) : QListModelInterface(parent)
+{
+ QFile f("../contacts/contacts.txt");
+ f.open(QIODevice::ReadOnly);
+ QTextStream ts(&f);
+ QString text = ts.readLine();
+ while(!text.isEmpty()) {
+ Contact *c = new Contact;
+ QStringList list = text.split(" ");
+ c->setFirstName(list[0]);
+ c->setLastName(list[1]);
+ for (int i = 2; i < list.count(); ++i)
+ c->addEmail(list[i]);
+ //contactList.append(c);
+ insertContact(c);
+
+ text = ts.readLine();
+ }
+ f.close();
+}
+
+ContactModel::~ContactModel()
+{
+ while (!contactList.isEmpty()) {
+ Contact *c = contactList.takeFirst();
+ delete c;
+ }
+}
+
+int ContactModel::count() const
+{
+ return contactList.count();
+}
+
+QHash<int,QVariant> ContactModel::data(int index, const QList<int> &roles) const
+{
+ QHash<int,QVariant> returnHash;
+
+ for (int i = 0; i < roles.size(); ++i) {
+ int role = roles.at(i);
+ QVariant info;
+ switch(role) {
+ case PortraitRole:
+ info = "contact.png";
+ break;
+ case FirstNameRole:
+ info = contactList.at(index)->firstName();
+ break;
+ case LastNameRole:
+ info = contactList.at(index)->lastName();
+ break;
+ case CompanyRole:
+ info = contactList.at(index)->company();
+ break;
+ case EmailsRole:
+ info = contactList.at(index)->emails();
+ break;
+ case AddressesRole:
+ //returns QVariant BOOL
+ info = QVariant::fromValue(contactList.at(index)->addresses());
+ break;
+ case NumbersRole:
+ info = QVariant::fromValue(contactList.at(index)->numbers());
+ break;
+ default:
+ break;
+ }
+ returnHash.insert(role, info);
+ }
+
+ return returnHash;
+}
+
+QString ContactModel::toString(int role) const
+{
+ switch(role) {
+ case PortraitRole:
+ return "portrait";
+ case FirstNameRole:
+ return "firstName";
+ case LastNameRole:
+ return "lastName";
+ case CompanyRole:
+ return "company";
+ case EmailsRole:
+ return "emails";
+ case AddressesRole:
+ return "addresses";
+ case NumbersRole:
+ return "numbers";
+ default:
+ return "";
+ }
+}
+
+QList<int> ContactModel::roles() const
+{
+ return QList<int>() << PortraitRole << FirstNameRole << LastNameRole << CompanyRole << EmailsRole << AddressesRole << NumbersRole;
+}
+
+void ContactModel::deleteContact(int index)
+{
+ delete contactList.takeAt(index);
+ emit itemsRemoved(index, 1);
+}
+
+int ContactModel::insertContact(Contact *contact)
+{
+ int index = 0;
+ QString fullName = contact->lastName();
+ index = findIndex(fullName);
+ contactList.insert(index, contact);
+ emit itemsInserted(index, 1);
+ return index;
+}
+
+
+//search - binary search algorithm lastname only
+
+int ContactModel::findIndex(QString &searchName) const
+{
+ int start = 0;
+ int end = contactList.size()-1;
+ int middle = 0;
+ QString middleString;
+
+ while (start <= end)
+ {
+ middle = (start+end)/2;
+ middleString = contactList.at(middle)->lastName();
+ if (isAfter(searchName, middleString) < 0) start = middle+1;
+ else if( isAfter(middleString, searchName) < 0) end = middle-1;
+ else return middle;
+ }
+ return start;
+}
+
+int ContactModel::isAfter(QString &name1, QString &name2) const
+{
+ //if c1 is after c2 alphabetically, return positive
+ int compString = QString::compare(name1, name2, Qt::CaseInsensitive);
+ return -compString;
+}
diff --git a/examples/declarative/support/contactmodel.h b/examples/declarative/support/contactmodel.h
new file mode 100644
index 0000000..e262358
--- /dev/null
+++ b/examples/declarative/support/contactmodel.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved.
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef _CONTACTMODEL_H_
+#define _CONTACTMODEL_H_
+
+#include <qlistmodelinterface.h>
+#include "contact.h"
+
+class ContactModel : public QListModelInterface
+{
+ Q_OBJECT
+public:
+ ContactModel(QObject *parent = 0);
+ ~ContactModel();
+
+ enum Roles {
+ PortraitRole,
+ FirstNameRole,
+ LastNameRole,
+ CompanyRole,
+ EmailsRole,
+ AddressesRole,
+ NumbersRole
+ };
+
+ int count() const;
+
+ QHash<int,QVariant> data(int index, const QList<int> &roles) const;
+ QList<int> roles() const;
+
+
+ QString toString(int role) const;
+
+ void deleteContact(int index);
+ int insertContact(Contact *contact);
+
+ int isAfter(QString &name1, QString &name2) const;
+ int findIndex(QString &searchName) const;
+
+private:
+ QList<Contact*> contactList;
+};
+
+#endif
diff --git a/examples/declarative/support/support.pro b/examples/declarative/support/support.pro
new file mode 100644
index 0000000..1da1a28
--- /dev/null
+++ b/examples/declarative/support/support.pro
@@ -0,0 +1,12 @@
+TEMPLATE = lib
+TARGET = QtFxSupport
+DEPENDPATH += .
+INCLUDEPATH += .
+MOC_DIR = .moc
+OBJECTS_DIR = .obj
+DESTDIR = ../../lib
+QT += script declarative
+
+HEADERS += contact.h contactmodel.h
+SOURCES += contact.cpp contactmodel.cpp
+
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_an_animation.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_an_animation.qml
new file mode 100644
index 0000000..06c9f5a
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1_Drawing_an_animation.qml
@@ -0,0 +1,22 @@
+<Rect id="page" width="240" height="180" color='black'>
+ <RemoveButton1
+ y="5"
+ anchors.right="{page.right}"
+ anchors.rightMargin="5"/>
+ <RemoveButton2
+ y="40"
+ anchors.right="{page.right}"
+ anchors.rightMargin="5"/>
+ <RemoveButton3
+ y="75"
+ anchors.right="{page.right}"
+ anchors.rightMargin="5"/>
+ <RemoveButton4
+ y="110"
+ anchors.right="{page.right}"
+ anchors.rightMargin="5"/>
+ <RemoveButton5
+ y="145"
+ anchors.right="{page.right}"
+ anchors.rightMargin="5"/>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton1.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton1.qml
new file mode 100644
index 0000000..dc3f505
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton1.qml
@@ -0,0 +1,4 @@
+<Rect id="removeButton"
+ width="30" height="30"
+ color="red"
+ radius="5"/>
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton2.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton2.qml
new file mode 100644
index 0000000..2ba488d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton2.qml
@@ -0,0 +1,10 @@
+<Rect id="removeButton"
+ width="30" height="30"
+ color="red"
+ radius="5">
+ <Image id="trashIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/trash.png"/>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton3.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton3.qml
new file mode 100644
index 0000000..9a364c5
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton3.qml
@@ -0,0 +1,23 @@
+<Rect id="removeButton"
+ width="230" height="30"
+ color="red"
+ radius="5">
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"/>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"/>
+ <Text id="text"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ anchors.left="{confirmIcon.right}" anchors.leftMargin="4"
+ anchors.right="{cancelIcon.left}" anchors.rightMargin="4"
+ font.bold="true"
+ color="white"
+ hAlign="AlignHCenter"
+ text="Remove"/>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton4.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton4.qml
new file mode 100644
index 0000000..45ca19d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton4.qml
@@ -0,0 +1,65 @@
+<Rect id="removeButton"
+ width="30" height="30"
+ color="red"
+ radius="5">
+ <resources>
+ <Script>
+ function toggle() {
+ print('removeButton.toggle()');
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+ </Script>
+ </resources>
+ <Image id="trashIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/trash.png"
+ opacity="1">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Text id="text"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ anchors.left="{confirmIcon.right}" anchors.leftMargin="4"
+ anchors.right="{cancelIcon.left}" anchors.rightMargin="4"
+ font.bold="true"
+ color="white"
+ hAlign="AlignHCenter"
+ text="Remove"
+ opacity="0"/>
+ <states>
+ <State name="opened">
+ <SetProperty target="{removeButton}" property="width" value="230"/>
+ <SetProperty target="{text}" property="opacity" value="1"/>
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{trashIcon}" property="opacity" value="0"/>
+ </State>
+ </states>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton5.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton5.qml
new file mode 100644
index 0000000..68c1838
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/RemoveButton5.qml
@@ -0,0 +1,70 @@
+<Rect id="removeButton"
+ width="30" height="30"
+ color="red"
+ radius="5">
+ <resources>
+ <Script>
+ function toggle() {
+ print('removeButton.toggle()');
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+ </Script>
+ </resources>
+ <Image id="trashIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/trash.png"
+ opacity="1">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Text id="text"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ anchors.left="{confirmIcon.right}" anchors.leftMargin="4"
+ anchors.right="{cancelIcon.left}" anchors.rightMargin="4"
+ font.bold="true"
+ color="white"
+ hAlign="AlignHCenter"
+ text="Remove"
+ opacity="0"/>
+ <states>
+ <State name="opened">
+ <SetProperty target="{removeButton}" property="width" value="230"/>
+ <SetProperty target="{text}" property="opacity" value="1"/>
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{trashIcon}" property="opacity" value="0"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="opened" reversible="true">
+ <NumericAnimation properties="opacity,x,width" duration="200"/>
+ </Transition>
+ </transitions>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml b/examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml
new file mode 100644
index 0000000..29fdf51
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/2_Reuse.qml
@@ -0,0 +1,34 @@
+<Rect id="page" width="480" height="360" color='black'>
+ <properties>
+ <Property name="mouseGrabbed" value="false"/>
+ </properties>
+ <Item x="0" y="0" width="240" height="180">
+ <ContactField1
+ y="5"
+ anchors.left="{parent.left}" anchors.leftMargin="5"
+ anchors.right="{parent.right}" anchors.rightMargin="5"/>
+ <ContactField2
+ y="40"
+ anchors.left="{parent.left}" anchors.leftMargin="5"
+ anchors.right="{parent.right}" anchors.rightMargin="5"/>
+ <ContactField3
+ y="75"
+ anchors.left="{parent.left}" anchors.leftMargin="5"
+ anchors.right="{parent.right}" anchors.rightMargin="5"
+ label="Phone Number"
+ icon="../shared/pics/phone.png"
+ value="123123"/>
+ </Item>
+ <Rect pen.color="gray" x="5" y="115" width="230" height="180" radius="5">
+ <Contact3 anchors.fill="{parent}"
+ label="Brian"
+ phone="123123"
+ email="brian@bigisp.com" />
+ </Rect>
+ <Rect pen.color="gray" x="245" y="115" width="230" height="180" radius="5">
+ <Contact4 anchors.fill="{parent}"
+ label="Brian"
+ phone="123123"
+ email="brian@bigisp.com" />
+ </Rect>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/Contact3.qml b/examples/declarative/tutorials/contacts/2_Reuse/Contact3.qml
new file mode 100644
index 0000000..fdd0c6d
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/Contact3.qml
@@ -0,0 +1,27 @@
+<Item id="contactDetails">
+ <properties>
+ <Property name="contactid" value=""/>
+ <Property name="label" onValueChanged="labelField.value = label"/>
+ <Property name="phone" onValueChanged="phoneField.value = phone"/>
+ <Property name="email" onValueChanged="emailField.value = email"/>
+ </properties>
+ <VerticalLayout id="layout"
+ anchors.fill="{parent}"
+ spacing="5"
+ margin="5">
+ <ContactField3 id="labelField"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"
+ label="Name"/>
+ <ContactField3 id="phoneField"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"
+ icon="../shared/pics/phone.png"
+ label="Phone"/>
+ <ContactField3 id="emailField"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"
+ icon="../shared/pics/email.png"
+ label="Email"/>
+ </VerticalLayout>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/Contact4.qml b/examples/declarative/tutorials/contacts/2_Reuse/Contact4.qml
new file mode 100644
index 0000000..b1882da
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/Contact4.qml
@@ -0,0 +1,27 @@
+<Item id="contactDetails">
+ <properties>
+ <Property name="contactid" value=""/>
+ <Property name="label" onValueChanged="labelField.value = label"/>
+ <Property name="phone" onValueChanged="phoneField.value = phone"/>
+ <Property name="email" onValueChanged="emailField.value = email"/>
+ </properties>
+ <VerticalLayout id="layout"
+ anchors.fill="{parent}"
+ spacing="5"
+ margin="5">
+ <ContactField4 id="labelField"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"
+ label="Name"/>
+ <ContactField4 id="phoneField"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"
+ icon="../shared/pics/phone.png"
+ label="Phone"/>
+ <ContactField4 id="emailField"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"
+ icon="../shared/pics/email.png"
+ label="Email"/>
+ </VerticalLayout>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/ContactField1.qml b/examples/declarative/tutorials/contacts/2_Reuse/ContactField1.qml
new file mode 100644
index 0000000..5547a3b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/ContactField1.qml
@@ -0,0 +1,17 @@
+<Item id="contactField"
+ clip="true"
+ height="30">
+ <RemoveButton1 id="removeButton"
+ anchors.right="{parent.right}"
+ anchors.top="{parent.top}" anchors.bottom="{parent.bottom}"/>
+ <Text id="fieldText"
+ width="{contactField.width-70}"
+ anchors.right="{removeButton.left}" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ font.bold="true"
+ color="white"
+ text="Phone Number"/>
+ <Image src="../shared/pics/phone.png"
+ anchors.right="{fieldText.left}" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"/>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/ContactField2.qml b/examples/declarative/tutorials/contacts/2_Reuse/ContactField2.qml
new file mode 100644
index 0000000..b69e03c
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/ContactField2.qml
@@ -0,0 +1,19 @@
+<Item id="contactField"
+ clip="true"
+ height="30">
+ <RemoveButton2 id="removeButton"
+ anchors.right="{parent.right}"
+ anchors.top="{parent.top}" anchors.bottom="{parent.bottom}"
+ expandedWidth="{contactField.width}"
+ onConfirmed="print('Clear field text'); fieldText.text=''"/>
+ <Text id="fieldText"
+ width="{contactField.width-70}"
+ anchors.right="{removeButton.left}" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ font.bold="true"
+ color="white"
+ text="Phone Number"/>
+ <Image src="../shared/pics/phone.png"
+ anchors.right="{fieldText.left}" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"/>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/ContactField3.qml b/examples/declarative/tutorials/contacts/2_Reuse/ContactField3.qml
new file mode 100644
index 0000000..f3a11f9
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/ContactField3.qml
@@ -0,0 +1,35 @@
+<Item id="contactField"
+ clip="true"
+ height="30">
+ <properties>
+ <Property name="label"/>
+ <Property name="icon"/>
+ <Property name="value"/>
+ </properties>
+ <RemoveButton3 id="removeButton"
+ anchors.right="{parent.right}"
+ anchors.top="{parent.top}" anchors.bottom="{parent.bottom}"
+ expandedWidth="{contactField.width}"
+ onConfirmed="print('Clear field text'); fieldText.text=''"/>
+ <FieldText3 id="fieldText"
+ width="{contactField.width-70}"
+ anchors.right="{removeButton.left}" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ label="{contactField.label}"
+ text="{contactField.value}"/>
+ <Image
+ anchors.right="{fieldText.left}" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="{contactField.icon}"/>
+ <states>
+ <State name="editingText" when="{fieldText.state == 'editing'}">
+ <SetProperty target="{removeButton.anchors}" property="rightMargin" value="-35"/>
+ <SetProperty target="{fieldText}" property="width" value="{contactField.width}"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState='' toState="*" reversible="true">
+ <NumericAnimation properties="width,rightMargin" duration="200"/>
+ </Transition>
+ </transitions>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/ContactField4.qml b/examples/declarative/tutorials/contacts/2_Reuse/ContactField4.qml
new file mode 100644
index 0000000..13ccbc0
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/ContactField4.qml
@@ -0,0 +1,35 @@
+<Item id="contactField"
+ clip="true"
+ height="30">
+ <properties>
+ <Property name="label"/>
+ <Property name="icon"/>
+ <Property name="value"/>
+ </properties>
+ <RemoveButton4 id="removeButton"
+ anchors.right="{parent.right}"
+ anchors.top="{parent.top}" anchors.bottom="{parent.bottom}"
+ expandedWidth="{contactField.width}"
+ onConfirmed="print('Clear field text'); fieldText.text=''"/>
+ <FieldText4 id="fieldText"
+ width="{contactField.width-70}"
+ anchors.right="{removeButton.left}" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ label="{contactField.label}"
+ text="{contactField.value}"/>
+ <Image
+ anchors.right="{fieldText.left}" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="{contactField.icon}"/>
+ <states>
+ <State name="editingText" when="{fieldText.state == 'editing'}">
+ <SetProperty target="{removeButton.anchors}" property="rightMargin" value="-35"/>
+ <SetProperty target="{fieldText}" property="width" value="{contactField.width}"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState='' toState="*" reversible="true">
+ <NumericAnimation properties="width,rightMargin" duration="200"/>
+ </Transition>
+ </transitions>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/FieldText3.qml b/examples/declarative/tutorials/contacts/2_Reuse/FieldText3.qml
new file mode 100644
index 0000000..c807aed
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/FieldText3.qml
@@ -0,0 +1,93 @@
+<Rect id="fieldText"
+ height="30"
+ radius="5"
+ color="black">
+ <properties>
+ <Property
+ name="text"
+ value=""
+ onValueChanged="reset()"/>
+ <Property
+ name="label"
+ value=""/>
+ </properties>
+ <signals>
+ <Signal name="confirmed"/>
+ </signals>
+ <resources>
+ <Script>
+ function edit() {
+ fieldText.state='editing';
+ }
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ fieldText.confirmed.emit();
+ }
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ }
+ </Script>
+ </resources>
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"
+ opacity="0"/>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"
+ opacity="0"/>
+ <TextEdit id="textEdit"
+ anchors.left="{parent.left}" anchors.leftMargin="0"
+ anchors.right="{parent.right}" anchors.rightMargin="0"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ color="white"
+ font.bold="true"
+ readOnly="true"
+ wrap="false"
+ />
+ <Text id="textLabel"
+ x="5" width="{parent.width-10}"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ hAlign="AlignHCenter"
+ color="#505050"
+ font.italic="true"
+ text="{fieldText.label}"
+ opacity="{textEdit.text != '' ? 0 : 1}">
+ <opacity>
+ <Behaviour>
+ <NumericAnimation property="opacity" duration="250"/>
+ </Behaviour>
+ </opacity>
+ </Text>
+ <MouseRegion anchors.fill="{cancelIcon}" onClicked="reset()"/>
+ <MouseRegion anchors.fill="{confirmIcon}" onClicked="confirm()"/>
+ <MouseRegion
+ id="editRegion"
+ anchors.fill="{textEdit}"
+ onClicked="edit()"/>
+ <states>
+ <State name="editing">
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{fieldText}" property="color" value="white"/>
+ <SetProperty target="{textEdit}" property="color" value="black"/>
+ <SetProperty target="{textEdit}" property="readOnly" value="false"/>
+ <SetProperty target="{textEdit}" property="focus" value="true"/>
+ <SetProperty target="{editRegion}" property="opacity" value="0"/>
+ <SetProperty target="{textEdit.anchors}" property="leftMargin" value="34"/>
+ <SetProperty target="{textEdit.anchors}" property="rightMargin" value="34"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState='' toState="*" reversible="true">
+ <NumericAnimation properties="opacity,leftMargin,rightMargin" duration="200"/>
+ <ColorAnimation duration="150"/>
+ </Transition>
+ </transitions>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/FieldText4.qml b/examples/declarative/tutorials/contacts/2_Reuse/FieldText4.qml
new file mode 100644
index 0000000..a4df42b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/FieldText4.qml
@@ -0,0 +1,98 @@
+<Rect id="fieldText"
+ height="30"
+ radius="5"
+ color="black">
+ <properties>
+ <Property
+ name="text"
+ value=""
+ onValueChanged="reset()"/>
+ <Property
+ name="label"
+ value=""/>
+ </properties>
+ <signals>
+ <Signal name="confirmed"/>
+ </signals>
+ <resources>
+ <Script>
+ function edit() {
+ if (!page.mouseGrabbed) {
+ fieldText.state='editing';
+ page.mouseGrabbed=true;
+ }
+ }
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ page.mouseGrabbed=false;
+ fieldText.confirmed.emit();
+ }
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ page.mouseGrabbed=false;
+ }
+ </Script>
+ </resources>
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"
+ opacity="0"/>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"
+ opacity="0"/>
+ <TextEdit id="textEdit"
+ anchors.left="{parent.left}" anchors.leftMargin="0"
+ anchors.right="{parent.right}" anchors.rightMargin="0"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ color="white"
+ font.bold="true"
+ readOnly="true"
+ wrap="false"
+ />
+ <Text id="textLabel"
+ x="5" width="{parent.width-10}"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ hAlign="AlignHCenter"
+ color="#505050"
+ font.italic="true"
+ text="{fieldText.label}"
+ opacity="{textEdit.text != '' ? 0 : 1}">
+ <opacity>
+ <Behaviour>
+ <NumericAnimation property="opacity" duration="250"/>
+ </Behaviour>
+ </opacity>
+ </Text>
+ <MouseRegion anchors.fill="{cancelIcon}" onClicked="reset()"/>
+ <MouseRegion anchors.fill="{confirmIcon}" onClicked="confirm()"/>
+ <MouseRegion
+ id="editRegion"
+ anchors.fill="{textEdit}"
+ onClicked="edit()"/>
+ <states>
+ <State name="editing">
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{fieldText}" property="color" value="white"/>
+ <SetProperty target="{textEdit}" property="color" value="black"/>
+ <SetProperty target="{textEdit}" property="readOnly" value="false"/>
+ <SetProperty target="{textEdit}" property="focus" value="true"/>
+ <SetProperty target="{editRegion}" property="opacity" value="0"/>
+ <SetProperty target="{textEdit.anchors}" property="leftMargin" value="34"/>
+ <SetProperty target="{textEdit.anchors}" property="rightMargin" value="34"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState='' toState="*" reversible="true">
+ <NumericAnimation properties="opacity,leftMargin,rightMargin" duration="200"/>
+ <ColorAnimation duration="150"/>
+ </Transition>
+ </transitions>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton1.qml b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton1.qml
new file mode 100644
index 0000000..68c1838
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton1.qml
@@ -0,0 +1,70 @@
+<Rect id="removeButton"
+ width="30" height="30"
+ color="red"
+ radius="5">
+ <resources>
+ <Script>
+ function toggle() {
+ print('removeButton.toggle()');
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+ </Script>
+ </resources>
+ <Image id="trashIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/trash.png"
+ opacity="1">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Text id="text"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ anchors.left="{confirmIcon.right}" anchors.leftMargin="4"
+ anchors.right="{cancelIcon.left}" anchors.rightMargin="4"
+ font.bold="true"
+ color="white"
+ hAlign="AlignHCenter"
+ text="Remove"
+ opacity="0"/>
+ <states>
+ <State name="opened">
+ <SetProperty target="{removeButton}" property="width" value="230"/>
+ <SetProperty target="{text}" property="opacity" value="1"/>
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{trashIcon}" property="opacity" value="0"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="opened" reversible="true">
+ <NumericAnimation properties="opacity,x,width" duration="200"/>
+ </Transition>
+ </transitions>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton2.qml b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton2.qml
new file mode 100644
index 0000000..d9ff4c5
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton2.qml
@@ -0,0 +1,76 @@
+<Rect id="removeButton"
+ width="30" height="30"
+ color="red"
+ radius="5">
+ <properties>
+ <Property name="expandedWidth" value="230"/>
+ </properties>
+ <signals>
+ <Signal name="confirmed"/>
+ </signals>
+ <resources>
+ <Script>
+ function toggle() {
+ print('removeButton.toggle()');
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+ </Script>
+ </resources>
+ <Image id="trashIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/trash.png"
+ opacity="1">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle(); removeButton.confirmed.emit()"/>
+ </Image>
+ <Text id="text"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ anchors.left="{confirmIcon.right}" anchors.leftMargin="4"
+ anchors.right="{cancelIcon.left}" anchors.rightMargin="4"
+ font.bold="true"
+ color="white"
+ hAlign="AlignHCenter"
+ text="Remove"
+ opacity="0"/>
+ <states>
+ <State name="opened">
+ <SetProperty target="{removeButton}" property="width" value="{removeButton.expandedWidth}"/>
+ <SetProperty target="{text}" property="opacity" value="1"/>
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{trashIcon}" property="opacity" value="0"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="opened" reversible="true">
+ <NumericAnimation properties="opacity,x,width" duration="200"/>
+ </Transition>
+ </transitions>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton3.qml b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton3.qml
new file mode 100644
index 0000000..d9ff4c5
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton3.qml
@@ -0,0 +1,76 @@
+<Rect id="removeButton"
+ width="30" height="30"
+ color="red"
+ radius="5">
+ <properties>
+ <Property name="expandedWidth" value="230"/>
+ </properties>
+ <signals>
+ <Signal name="confirmed"/>
+ </signals>
+ <resources>
+ <Script>
+ function toggle() {
+ print('removeButton.toggle()');
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ } else {
+ removeButton.state = 'opened';
+ }
+ }
+ </Script>
+ </resources>
+ <Image id="trashIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/trash.png"
+ opacity="1">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle(); removeButton.confirmed.emit()"/>
+ </Image>
+ <Text id="text"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ anchors.left="{confirmIcon.right}" anchors.leftMargin="4"
+ anchors.right="{cancelIcon.left}" anchors.rightMargin="4"
+ font.bold="true"
+ color="white"
+ hAlign="AlignHCenter"
+ text="Remove"
+ opacity="0"/>
+ <states>
+ <State name="opened">
+ <SetProperty target="{removeButton}" property="width" value="{removeButton.expandedWidth}"/>
+ <SetProperty target="{text}" property="opacity" value="1"/>
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{trashIcon}" property="opacity" value="0"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="opened" reversible="true">
+ <NumericAnimation properties="opacity,x,width" duration="200"/>
+ </Transition>
+ </transitions>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton4.qml b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton4.qml
new file mode 100644
index 0000000..a489e95
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/2_Reuse/RemoveButton4.qml
@@ -0,0 +1,80 @@
+<Rect id="removeButton"
+ width="30" height="30"
+ color="red"
+ radius="5">
+ <properties>
+ <Property name="expandedWidth" value="230"/>
+ </properties>
+ <signals>
+ <Signal name="confirmed"/>
+ </signals>
+ <resources>
+ <Script>
+ function toggle() {
+ print('removeButton.toggle()');
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ page.mouseGrabbed=false;
+ } else {
+ if (!page.mouseGrabbed) {
+ removeButton.state = 'opened';
+ page.mouseGrabbed=true;
+ }
+ }
+ }
+ </Script>
+ </resources>
+ <Image id="trashIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/trash.png"
+ opacity="1">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle(); removeButton.confirmed.emit()"/>
+ </Image>
+ <Text id="text"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ anchors.left="{confirmIcon.right}" anchors.leftMargin="4"
+ anchors.right="{cancelIcon.left}" anchors.rightMargin="4"
+ font.bold="true"
+ color="white"
+ hAlign="AlignHCenter"
+ text="Remove"
+ opacity="0"/>
+ <states>
+ <State name="opened">
+ <SetProperty target="{removeButton}" property="width" value="{removeButton.expandedWidth}"/>
+ <SetProperty target="{text}" property="opacity" value="1"/>
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{trashIcon}" property="opacity" value="0"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="opened" reversible="true">
+ <NumericAnimation properties="opacity,x,width" duration="200"/>
+ </Transition>
+ </transitions>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml b/examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml
new file mode 100644
index 0000000..ed2a3dc
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/3_Collections.qml
@@ -0,0 +1,8 @@
+<Rect id="page" width="480" height="640" color='black'>
+ <properties>
+ <Property name="mouseGrabbed" value="false"/>
+ </properties>
+ <ContactView1 x="0" y="0" width="240" height="320"/>
+ <ContactView2 x="240" y="0" width="240" height="320"/>
+ <ContactView3 x="0" y="320" width="240" height="320"/>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/3_Collections/Button.qml b/examples/declarative/tutorials/contacts/3_Collections/Button.qml
new file mode 100644
index 0000000..8290d35
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/Button.qml
@@ -0,0 +1,38 @@
+<Item id="button" width="30" height="30">
+ <properties>
+ <Property name="icon"/>
+ </properties>
+ <signals>
+ <Signal name="clicked"/>
+ </signals>
+ <Rect id="buttonRect"
+ anchors.fill="{parent}"
+ color="lightgreen"
+ radius="5">
+ <Image id="iconImage"
+ src="{button.icon}"
+ anchors.horizontalCenter="{buttonRect.horizontalCenter}"
+ anchors.verticalCenter="{buttonRect.verticalCenter}"/>
+ <MouseRegion id="buttonMouseRegion"
+ anchors.fill="{buttonRect}"
+ onClicked="button.clicked.emit()"/>
+ <states>
+ <State name="pressed" when="{buttonMouseRegion.pressed == true}">
+ <SetProperty target="{buttonRect}" property="color" value="green"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="pressed">
+ <ColorAnimation duration="200"/>
+ </Transition>
+ <Transition fromState="pressed" toState="*">
+ <ColorAnimation duration="1000"/>
+ </Transition>
+ </transitions>
+ </Rect>
+ <opacity>
+ <Behaviour>
+ <NumericAnimation property="opacity" duration="250"/>
+ </Behaviour>
+ </opacity>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/3_Collections/Contact.qml b/examples/declarative/tutorials/contacts/3_Collections/Contact.qml
new file mode 100644
index 0000000..f620c25
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/Contact.qml
@@ -0,0 +1,28 @@
+<Item id="contactDetails"
+ anchors.fill="{parent}">
+ <properties>
+ <Property name="contactid" value=""/>
+ <Property name="label" onValueChanged="labelField.value = label"/>
+ <Property name="phone" onValueChanged="phoneField.value = phone"/>
+ <Property name="email" onValueChanged="emailField.value = email"/>
+ </properties>
+ <VerticalLayout id="layout"
+ anchors.fill="{parent}"
+ spacing="5"
+ margin="5">
+ <ContactField id="labelField"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"
+ label="Name"/>
+ <ContactField id="phoneField"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"
+ icon="../shared/pics/phone.png"
+ label="Phone"/>
+ <ContactField id="emailField"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"
+ icon="../shared/pics/email.png"
+ label="Email"/>
+ </VerticalLayout>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/3_Collections/ContactField.qml b/examples/declarative/tutorials/contacts/3_Collections/ContactField.qml
new file mode 100644
index 0000000..819914c
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/ContactField.qml
@@ -0,0 +1,35 @@
+<Item id="contactField"
+ clip="true"
+ height="30">
+ <properties>
+ <Property name="label"/>
+ <Property name="icon"/>
+ <Property name="value"/>
+ </properties>
+ <RemoveButton id="removeButton"
+ anchors.right="{parent.right}"
+ anchors.top="{parent.top}" anchors.bottom="{parent.bottom}"
+ expandedWidth="{contactField.width}"
+ onConfirmed="print('Clear field text'); fieldText.text=''"/>
+ <FieldText id="fieldText"
+ width="{contactField.width-70}"
+ anchors.right="{removeButton.left}" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ label="{contactField.label}"
+ text="{contactField.value}"/>
+ <Image
+ anchors.right="{fieldText.left}" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="{contactField.icon}"/>
+ <states>
+ <State name="editingText" when="{fieldText.state == 'editing'}">
+ <SetProperty target="{removeButton.anchors}" property="rightMargin" value="-35"/>
+ <SetProperty target="{fieldText}" property="width" value="{contactField.width}"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState='' toState="*" reversible="true">
+ <NumericAnimation properties="width,rightMargin" duration="200"/>
+ </Transition>
+ </transitions>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/3_Collections/ContactView1.qml b/examples/declarative/tutorials/contacts/3_Collections/ContactView1.qml
new file mode 100644
index 0000000..d6f7bad
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/ContactView1.qml
@@ -0,0 +1,22 @@
+<Item id="contacts">
+ <resources>
+ <SqlConnection id="contactDatabase" name="qmlConnection" driver="QSQLITE" databaseName="../shared/contacts.sqlite"/>
+ <SqlQuery id="contactList" connection="{contactDatabase}">
+ <query>SELECT recid, label, email, phone FROM contacts ORDER BY label, recid</query>
+ </SqlQuery>
+ <Component id="contactDelegate">
+ <Text
+ x="40" y="12"
+ width="{contactListView.width-30}"
+ height="30"
+ color="white"
+ font.bold="true"
+ text="{model.label}"/>
+ </Component>
+ </resources>
+ <ListView id="contactListView"
+ anchors.fill="{parent}"
+ clip="true"
+ model="{contactList}"
+ delegate="{contactDelegate}"/>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/3_Collections/ContactView2.qml b/examples/declarative/tutorials/contacts/3_Collections/ContactView2.qml
new file mode 100644
index 0000000..da1e5db
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/ContactView2.qml
@@ -0,0 +1,62 @@
+<Item id="contacts">
+ <resources>
+ <SqlConnection id="contactDatabase" name="qmlConnection" driver="QSQLITE" databaseName="../shared/contacts.sqlite"/>
+ <SqlQuery id="contactList" connection="{contactDatabase}">
+ <query>SELECT recid AS contactid, label, email, phone FROM contacts ORDER BY label, recid</query>
+ </SqlQuery>
+ <Component id="contactDelegate">
+ <Item id="wrapper"
+ x="0"
+ width="{ListView.view.width}" height="34">
+ <Text id="label"
+ x="40" y="12"
+ width="{parent.width-30}"
+ text="{model.label}"
+ color="white"
+ font.bold="true">
+ </Text>
+ <MouseRegion
+ anchors.fill="{label}"
+ onClicked="wrapper.state='opened'"/>
+ <Contact id="details"
+ anchors.fill="{parent}"
+ contactid="{model.contactid}"
+ label="{model.label}"
+ email="{model.email}"
+ phone="{model.phone}"
+ opacity="0"/>
+ <states>
+ <State name='opened'>
+ <SetProperty target="{wrapper}" property="height" value="{contactListView.height}"/>
+ <SetProperty target="{contactListView}" property="yPosition" value="{wrapper.y}"/>
+ <SetProperty target="{contactListView}" property="locked" value="1"/>
+ <SetProperty target="{label}" property="opacity" value="0"/>
+ <SetProperty target="{details}" property="opacity" value="1"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition>
+ <NumericAnimation duration="500" properties="yPosition,height,opacity"/>
+ </Transition>
+ </transitions>
+ <Connection sender="{cancelEditButton}" signal="clicked()">
+ if (wrapper.state == 'opened') {
+ wrapper.state = '';
+ }
+ </Connection>
+ </Item>
+ </Component>
+ </resources>
+ <Button id="cancelEditButton"
+ anchors.top="{parent.top}" anchors.topMargin="5"
+ anchors.right="{parent.right}" anchors.rightMargin="5"
+ icon="../shared/pics/cancel.png"/>
+ <ListView id="contactListView"
+ anchors.left="{parent.left}"
+ anchors.right="{parent.right}"
+ anchors.top="{cancelEditButton.bottom}"
+ anchors.bottom="{parent.bottom}"
+ clip="true"
+ model="{contactList}"
+ delegate="{contactDelegate}"/>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/3_Collections/ContactView3.qml b/examples/declarative/tutorials/contacts/3_Collections/ContactView3.qml
new file mode 100644
index 0000000..a5d88a1
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/ContactView3.qml
@@ -0,0 +1,67 @@
+<Item id="contacts">
+ <resources>
+ <SqlConnection id="contactDatabase" name="qmlConnection" driver="QSQLITE" databaseName="../shared/contacts.sqlite"/>
+ <SqlQuery id="contactList" connection="{contactDatabase}">
+ <query>SELECT recid AS contactid, label, email, phone FROM contacts ORDER BY label, recid</query>
+ </SqlQuery>
+ <Component id="contactDelegate">
+ <Item id="wrapper"
+ x="0"
+ width="{ListView.view.width}" height="34">
+ <Text id="label"
+ x="40" y="12"
+ width="{parent.width-30}"
+ text="{model.label}"
+ color="white"
+ font.bold="true">
+ </Text>
+ <MouseRegion
+ anchors.fill="{label}">
+ <onClicked>
+ Details.qml = 'Contact.qml';
+ wrapper.state='opened';
+ </onClicked>
+ </MouseRegion>
+ <Item id="Details"
+ anchors.fill="{wrapper}"
+ opacity="0">
+ <Bind target="{Details.qmlItem}" property="contactid" value="{model.contactid}"/>
+ <Bind target="{Details.qmlItem}" property="label" value="{model.label}"/>
+ <Bind target="{Details.qmlItem}" property="phone" value="{model.phone}"/>
+ <Bind target="{Details.qmlItem}" property="email" value="{model.email}"/>
+ </Item>
+ <states>
+ <State name='opened'>
+ <SetProperty target="{wrapper}" property="height" value="{contactListView.height}"/>
+ <SetProperty target="{contactListView}" property="yPosition" value="{wrapper.y}"/>
+ <SetProperty target="{contactListView}" property="locked" value="1"/>
+ <SetProperty target="{label}" property="opacity" value="0"/>
+ <SetProperty target="{Details}" property="opacity" value="1"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition>
+ <NumericAnimation duration="500" properties="yPosition,height,opacity"/>
+ </Transition>
+ </transitions>
+ <Connection sender="{cancelEditButton}" signal="clicked()">
+ if (wrapper.state == 'opened') {
+ wrapper.state = '';
+ }
+ </Connection>
+ </Item>
+ </Component>
+ </resources>
+ <Button id="cancelEditButton"
+ anchors.top="{parent.top}" anchors.topMargin="5"
+ anchors.right="{parent.right}" anchors.rightMargin="5"
+ icon="../shared/pics/cancel.png"/>
+ <ListView id="contactListView"
+ anchors.left="{parent.left}"
+ anchors.right="{parent.right}"
+ anchors.top="{cancelEditButton.bottom}"
+ anchors.bottom="{parent.bottom}"
+ clip="true"
+ model="{contactList}"
+ delegate="{contactDelegate}"/>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/3_Collections/FieldText.qml b/examples/declarative/tutorials/contacts/3_Collections/FieldText.qml
new file mode 100644
index 0000000..a4df42b
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/FieldText.qml
@@ -0,0 +1,98 @@
+<Rect id="fieldText"
+ height="30"
+ radius="5"
+ color="black">
+ <properties>
+ <Property
+ name="text"
+ value=""
+ onValueChanged="reset()"/>
+ <Property
+ name="label"
+ value=""/>
+ </properties>
+ <signals>
+ <Signal name="confirmed"/>
+ </signals>
+ <resources>
+ <Script>
+ function edit() {
+ if (!page.mouseGrabbed) {
+ fieldText.state='editing';
+ page.mouseGrabbed=true;
+ }
+ }
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ page.mouseGrabbed=false;
+ fieldText.confirmed.emit();
+ }
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ page.mouseGrabbed=false;
+ }
+ </Script>
+ </resources>
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"
+ opacity="0"/>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"
+ opacity="0"/>
+ <TextEdit id="textEdit"
+ anchors.left="{parent.left}" anchors.leftMargin="0"
+ anchors.right="{parent.right}" anchors.rightMargin="0"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ color="white"
+ font.bold="true"
+ readOnly="true"
+ wrap="false"
+ />
+ <Text id="textLabel"
+ x="5" width="{parent.width-10}"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ hAlign="AlignHCenter"
+ color="#505050"
+ font.italic="true"
+ text="{fieldText.label}"
+ opacity="{textEdit.text != '' ? 0 : 1}">
+ <opacity>
+ <Behaviour>
+ <NumericAnimation property="opacity" duration="250"/>
+ </Behaviour>
+ </opacity>
+ </Text>
+ <MouseRegion anchors.fill="{cancelIcon}" onClicked="reset()"/>
+ <MouseRegion anchors.fill="{confirmIcon}" onClicked="confirm()"/>
+ <MouseRegion
+ id="editRegion"
+ anchors.fill="{textEdit}"
+ onClicked="edit()"/>
+ <states>
+ <State name="editing">
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{fieldText}" property="color" value="white"/>
+ <SetProperty target="{textEdit}" property="color" value="black"/>
+ <SetProperty target="{textEdit}" property="readOnly" value="false"/>
+ <SetProperty target="{textEdit}" property="focus" value="true"/>
+ <SetProperty target="{editRegion}" property="opacity" value="0"/>
+ <SetProperty target="{textEdit.anchors}" property="leftMargin" value="34"/>
+ <SetProperty target="{textEdit.anchors}" property="rightMargin" value="34"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState='' toState="*" reversible="true">
+ <NumericAnimation properties="opacity,leftMargin,rightMargin" duration="200"/>
+ <ColorAnimation duration="150"/>
+ </Transition>
+ </transitions>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/3_Collections/RemoveButton.qml b/examples/declarative/tutorials/contacts/3_Collections/RemoveButton.qml
new file mode 100644
index 0000000..a489e95
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/3_Collections/RemoveButton.qml
@@ -0,0 +1,80 @@
+<Rect id="removeButton"
+ width="30" height="30"
+ color="red"
+ radius="5">
+ <properties>
+ <Property name="expandedWidth" value="230"/>
+ </properties>
+ <signals>
+ <Signal name="confirmed"/>
+ </signals>
+ <resources>
+ <Script>
+ function toggle() {
+ print('removeButton.toggle()');
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ page.mouseGrabbed=false;
+ } else {
+ if (!page.mouseGrabbed) {
+ removeButton.state = 'opened';
+ page.mouseGrabbed=true;
+ }
+ }
+ }
+ </Script>
+ </resources>
+ <Image id="trashIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/trash.png"
+ opacity="1">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="cancelIcon"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/cancel.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle()"/>
+ </Image>
+ <Image id="confirmIcon"
+ width="22" height="22"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ src="../shared/pics/ok.png"
+ opacity="0">
+ <MouseRegion
+ anchors.fill="{parent}"
+ onClicked="toggle(); removeButton.confirmed.emit()"/>
+ </Image>
+ <Text id="text"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ anchors.left="{confirmIcon.right}" anchors.leftMargin="4"
+ anchors.right="{cancelIcon.left}" anchors.rightMargin="4"
+ font.bold="true"
+ color="white"
+ hAlign="AlignHCenter"
+ text="Remove"
+ opacity="0"/>
+ <states>
+ <State name="opened">
+ <SetProperty target="{removeButton}" property="width" value="{removeButton.expandedWidth}"/>
+ <SetProperty target="{text}" property="opacity" value="1"/>
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{trashIcon}" property="opacity" value="0"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="opened" reversible="true">
+ <NumericAnimation properties="opacity,x,width" duration="200"/>
+ </Transition>
+ </transitions>
+</Rect>
diff --git a/examples/declarative/tutorials/contacts/shared/contacts.sqlite b/examples/declarative/tutorials/contacts/shared/contacts.sqlite
new file mode 100644
index 0000000..7347adc
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/contacts.sqlite
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/cancel.png b/examples/declarative/tutorials/contacts/shared/pics/cancel.png
new file mode 100644
index 0000000..ecc9533
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/cancel.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/email.png b/examples/declarative/tutorials/contacts/shared/pics/email.png
new file mode 100644
index 0000000..04b3865
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/email.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/new.png b/examples/declarative/tutorials/contacts/shared/pics/new.png
new file mode 100644
index 0000000..c7ebac3
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/new.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/ok.png b/examples/declarative/tutorials/contacts/shared/pics/ok.png
new file mode 100644
index 0000000..5795f04
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/ok.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/phone.png b/examples/declarative/tutorials/contacts/shared/pics/phone.png
new file mode 100644
index 0000000..fc9c222
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/phone.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/search.png b/examples/declarative/tutorials/contacts/shared/pics/search.png
new file mode 100644
index 0000000..cc74e69
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/search.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/shared/pics/trash.png b/examples/declarative/tutorials/contacts/shared/pics/trash.png
new file mode 100644
index 0000000..2042595
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/shared/pics/trash.png
Binary files differ
diff --git a/examples/declarative/tutorials/contacts/t8/Button.qml b/examples/declarative/tutorials/contacts/t8/Button.qml
new file mode 100644
index 0000000..63c4636
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/t8/Button.qml
@@ -0,0 +1,33 @@
+<Item width="30" height="30" id="button">
+ <properties>
+ <Property name="icon"/>
+ </properties>
+ <signals>
+ <Signal name="clicked"/>
+ </signals>
+ <Rect id="buttonRect" color="lightgreen" anchors.fill="{parent}" radius="5">
+ <Image id="iconImage"
+ src="{button.icon}"
+ anchors.horizontalCenter="{buttonRect.horizontalCenter}"
+ anchors.verticalCenter="{buttonRect.verticalCenter}"/>
+ <MouseRegion id="buttonMouseRegion" anchors.fill="{buttonRect}" onClicked="button.clicked.emit()"/>
+ <states>
+ <State name="pressed" when="{buttonMouseRegion.pressed == true}">
+ <SetProperty target="{buttonRect}" property="color" value="green"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="pressed">
+ <ColorAnimation duration="200"/>
+ </Transition>
+ <Transition fromState="pressed" toState="*">
+ <ColorAnimation duration="1000"/>
+ </Transition>
+ </transitions>
+ </Rect>
+ <opacity>
+ <Behaviour>
+ <NumericAnimation property="opacity" duration="250"/>
+ </Behaviour>
+ </opacity>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/t8/Contact.qml b/examples/declarative/tutorials/contacts/t8/Contact.qml
new file mode 100644
index 0000000..5852b43
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/t8/Contact.qml
@@ -0,0 +1,80 @@
+<Item id="contactDetails" anchors.fill="{parent}">
+ <properties>
+ <Property name="label" onValueChanged="c_label.value = label"/>
+ <Property name="contactid" value=""/>
+ <Property name="phone" onValueChanged="c_phone.value = phone"/>
+ <Property name="email" onValueChanged="c_email.value = email"/>
+ <Property name="mode" value="closed"/>
+ </properties>
+ <signals>
+ <Signal name="open"/>
+ <Signal name="close"/>
+ <Signal name="confirm"/>
+ <Signal name="cancel"/>
+ </signals>
+ <resources>
+ <SqlQuery id="updateContactQuery" connection="{contactDatabase}">
+ <query>UPDATE contacts SET label = :l, email = :e, phone = :p WHERE recid = :r</query>
+ <bindings>
+ <SqlBind name=":r" value="{contactid}"/>
+ <SqlBind name=":l" value="{c_label.value}"/>
+ <SqlBind name=":e" value="{c_email.value}"/>
+ <SqlBind name=":p" value="{c_phone.value}"/>
+ </bindings>
+ </SqlQuery>
+ <SqlQuery id="insertContactQuery" connection="{contactDatabase}">
+ <query>INSERT INTO contacts (label, email, phone) VALUES(:l, :e, :p)</query>
+ <bindings>
+ <SqlBind name=":l" value="{c_label.value}"/>
+ <SqlBind name=":e" value="{c_email.value}"/>
+ <SqlBind name=":p" value="{c_phone.value}"/>
+ </bindings>
+ </SqlQuery>
+ </resources>
+ <Connection sender="{contactDetails}" signal="cancel()">
+ c_label.value = label;
+ c_phone.value = phone;
+ c_email.value = email;
+ contactDetails.close.emit();
+ </Connection>
+ <Connection sender="{contactDetails}" signal="confirm()">
+ if (c_label.value != '') {
+ if (contactid == '') {
+ insertContactQuery.exec();
+ c_label.value = label;
+ c_phone.value = phone;
+ c_email.value = email;
+ } else {
+ updateContactQuery.exec();
+ }
+ contactList.exec();
+ }
+ contactDetails.close.emit();
+ </Connection>
+ <VerticalLayout id="layout" anchors.fill="{parent}" spacing="5" margin="5">
+ <Field id="c_label" label="Name"
+ editable="{mode == 'opened' ? 1 : 0}"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"/>
+ <Field id="c_phone" icon="../shared/pics/phone.png" label="Phone"
+ opacity="0" editable="{mode == 'opened' ? 1 : 0}"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"/>
+ <Field id="c_email" icon="../shared/pics/email.png" label="Email"
+ opacity="0" editable="{mode == 'opened' ? 1 : 0}"
+ anchors.left="{layout.left}" anchors.leftMargin="5"
+ anchors.right="{layout.right}" anchors.rightMargin="5"/>
+ </VerticalLayout>
+ <MouseRegion anchors.fill="{contactDetails}" onClicked="contactDetails.open.emit()" z="{mode=='opened' ? -1 : 1}"/>
+ <states>
+ <State name="opened" when="{mode == 'opened'}">
+ <SetProperty target="{c_phone}" property="opacity" value="1"/>
+ <SetProperty target="{c_email}" property="opacity" value="1"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="opened" reversible="true">
+ <NumericAnimation target="{contactFields}" properties="opacity" duration="200"/>
+ </Transition>
+ </transitions>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/t8/Field.qml b/examples/declarative/tutorials/contacts/t8/Field.qml
new file mode 100644
index 0000000..0191ef8
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/t8/Field.qml
@@ -0,0 +1,54 @@
+<Item height="30" width="200" id="field">
+ <properties>
+ <Property name="value" onValueChanged="fieldText.text=field.value"/>
+ <Property name="icon"/>
+ <Property name="editable" value="0"/>
+ <Property name="label"/>
+ </properties>
+ <Item id="fieldSelector" width="30" height="30"
+ x="0"
+ anchors.top="{parent.top}"
+ anchors.bottom="{parent.bottom}">
+ <Image src="{field.icon}"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ anchors.horizontalCenter="{parent.horizontalCenter}"/>
+ </Item>
+ <FieldText id="fieldText"
+ label="{field.label}"
+ width="{field.width-70}"
+ anchors.left="{fieldSelector.right}"
+ anchors.leftMargin="5"
+ anchors.top="{parent.top}"
+ anchors.bottom="{parent.bottom}"
+ onTextEdited="field.value = fieldText.text"/>
+ <FieldRemover id="fieldRemover"
+ anchors.left="{fieldText.right}"
+ anchors.leftMargin="5"
+ anchors.top="{parent.top}"
+ anchors.bottom="{parent.bottom}"
+ onConfirm="fieldText.text = ''"
+ opacity="{field.editable}"/>
+ <states>
+ <State name="textFill" when="{fieldText.open == 'true'}">
+ <SetProperty target="{fieldText}" property="width" value="{field.width}"/>
+ <SetProperty target="{fieldText}" property="x" value="0"/>
+ <SetProperty target="{fieldRemover}" property="opacity" value="0"/>
+ <SetProperty target="{fieldSelector}" property="opacity" value="0"/>
+ <SetProperty target="{fieldSelector}" property="x" value="{-5-fieldSelector.width}"/>
+ </State>
+ <State name="removerFill" when="{fieldRemover.open == 'true'}">
+ <SetProperty target="{fieldRemover}" property="width" value="{field.width}"/>
+ <SetProperty target="{fieldRemover}" property="x" value="0"/>
+ <SetProperty target="{fieldText}" property="opacity" value="0"/>
+ <SetProperty target="{fieldSelector}" property="opacity" value="0"/>
+ <SetProperty target="{fieldSelector}" property="x" value="{-10-fieldText.width-fieldSelector.width}"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="*">
+ <NumericAnimation target="{fieldSelector}" properties="width,x,opacity" duration="200"/>
+ <NumericAnimation target="{fieldText}" properties="width,x,opacity" duration="200"/>
+ <NumericAnimation target="{fieldRemover}" properties="width,x,opacity" duration="200"/>
+ </Transition>
+ </transitions>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/t8/FieldRemover.qml b/examples/declarative/tutorials/contacts/t8/FieldRemover.qml
new file mode 100644
index 0000000..a7dad64
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/t8/FieldRemover.qml
@@ -0,0 +1,57 @@
+<Item height="30" width="30" id="fieldRemover" clip="true">
+ <properties>
+ <Property name="open" value="false"/>
+ </properties>
+ <signals>
+ <Signal name="confirm"/>
+ </signals>
+ <resources>
+ <Script>
+ function toggle() {
+ if (fieldRemover.state=='opened') {
+ fieldRemover.state='';
+ open='false';
+ Page.mouseGrabbed='false';
+ } else {
+ if (Page.mouseGrabbed != 'true') {
+ fieldRemover.state='opened';
+ open='true';
+ Page.mouseGrabbed='true';
+ }
+ }
+ }
+ </Script>
+ </resources>
+ <Rect id="border" anchors.fill="{parent}" color="red" radius="5"/>
+ <Image id="trashIcon" src="../shared/pics/trash.png"
+ width="22" height="22"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"/>
+ <Image id="cancelIcon" src="../shared/pics/cancel.png"
+ width="22" height="22" opacity="0"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"/>
+ <Image id="confirmIcon" src="../shared/pics/ok.png"
+ width="22" height="22" opacity="0"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"/>
+ <Text id="text" opacity="0" text="Remove" font.bold="true" color="white" hAlign="AlignHCenter"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ anchors.left="{confirmIcon.right}" anchors.leftMargin="4"
+ anchors.right="{cancelIcon.left}" anchors.rightMargin="4"/>
+ <MouseRegion anchors.fill="{confirmIcon}" onClicked="toggle(); fieldRemover.confirm.emit()"/>
+ <MouseRegion anchors.fill="{trashIcon}" onClicked="toggle()"/>
+ <states>
+ <State name="opened">
+ <SetProperty target="{text}" property="opacity" value="1"/>
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{trashIcon}" property="opacity" value="0"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="opened" reversible="true">
+ <NumericAnimation properties="opacity,x,width" duration="200"/>
+ </Transition>
+ </transitions>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/t8/FieldText.qml b/examples/declarative/tutorials/contacts/t8/FieldText.qml
new file mode 100644
index 0000000..d3a158a
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/t8/FieldText.qml
@@ -0,0 +1,89 @@
+<Item height="30" id="fieldText">
+ <properties>
+ <Property name="open" value="false"/>
+ <Property name="text" value="" onValueChanged="setText(fieldText.text)"/>
+ <Property name="label" value=""/>
+ </properties>
+ <signals>
+ <Signal name="textEdited"/>
+ </signals>
+ <resources>
+ <Script>
+ function start() {
+ if (Page.mouseGrabbed != 'true') {
+ fieldText.state='editing';
+ open='true';
+ Page.mouseGrabbed='true';
+ }
+ }
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ open='false';
+ Page.mouseGrabbed='false';
+ fieldText.textEdited.emit();
+ }
+ function cancel() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ open='false';
+ Page.mouseGrabbed='false';
+ }
+ function setText(value) {
+ if (textEdit.text != value) {
+ fieldText.state='';
+ open='false';
+ textEdit.text = value;
+ }
+ }
+ </Script>
+ </resources>
+ <Rect id="border" radius="5" anchors.fill="{parent}" color="{field.editable == 1 ? '#202020' : '#000000'}">
+ <TextEdit id="textEdit" vAlign="AlignVCenter" text=""
+ readOnly="true" font.bold="true" wrap="false" color="white"
+ x="5" width="{parent.width-10}"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ />
+ <Text id="textLabel" vAlign="AlignVCenter" hAlign="AlignHCenter"
+ color="#505050" font.italic="true"
+ anchors.fill="{border}" text="{fieldText.label}"
+ opacity="{textEdit.text == '' ? 1 : 0}">
+ <opacity>
+ <Behaviour>
+ <NumericAnimation target="{textLabel}" property="opacity" duration="250"/>
+ </Behaviour>
+ </opacity>
+ </Text>
+ <Image id="cancelIcon" src="../shared/pics/cancel.png"
+ width="22" height="22" opacity="0"
+ anchors.right="{parent.right}" anchors.rightMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"/>
+ <Image id="confirmIcon" src="../shared/pics/ok.png"
+ width="22" height="22" opacity="0"
+ anchors.left="{parent.left}" anchors.leftMargin="4"
+ anchors.verticalCenter="{parent.verticalCenter}"/>
+ <MouseRegion anchors.fill="{cancelIcon}" onClicked="cancel()"/>
+ <MouseRegion anchors.fill="{confirmIcon}" onClicked="confirm()"/>
+ <MouseRegion id="editRegion" anchors.fill="{textEdit}" onClicked="start()"/>
+ </Rect>
+ <states>
+ <State name="editing">
+ <SetProperty target="{confirmIcon}" property="opacity" value="1"/>
+ <SetProperty target="{cancelIcon}" property="opacity" value="1"/>
+ <SetProperty target="{border}" property="color" value="white"/>
+ <SetProperty target="{textEdit}" property="color" value="black"/>
+ <SetProperty target="{textEdit}" property="readOnly" value="false"/>
+ <SetProperty target="{textEdit}" property="focus" value="true"/>
+ <SetProperty target="{textEdit}" property="x" value="35"/>
+ <SetProperty target="{editRegion}" property="opacity" value="0"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState='' toState="*" reversible="true">
+ <NumericAnimation target="{textEdit}" properties="x" duration="200"/>
+ <NumericAnimation target="{confirmIcon}" properties="opacity" duration="200"/>
+ <NumericAnimation target="{cancelIcon}" properties="opacity" duration="200"/>
+ <ColorAnimation duration="150"/>
+ </Transition>
+ </transitions>
+</Item>
diff --git a/examples/declarative/tutorials/contacts/t8/SearchBar.qml b/examples/declarative/tutorials/contacts/t8/SearchBar.qml
new file mode 100644
index 0000000..f8e1a6a
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/t8/SearchBar.qml
@@ -0,0 +1,16 @@
+<Item height="30" width="{parent.width}">
+ <properties>
+ <Property name="text" value="{searchEdit.text}"/>
+ </properties>
+ <Rect color="white" anchors.fill="{parent}">
+ <Image id="searchIcon" src="../shared/pics/search.png"
+ anchors.left="{parent.left}" anchors.leftMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"/>
+ <TextEdit id="searchEdit" focus="{Page.listShown == 1}"
+ anchors.left="{searchIcon.right}" anchors.right="{parent.right}"
+ anchors.leftMargin="5" anchors.rightMargin="5"
+ anchors.verticalCenter="{parent.verticalCenter}"
+ readOnly="false" wrap="false"/>
+ </Rect>
+</Item>
+
diff --git a/examples/declarative/tutorials/contacts/t8/contacts.qml b/examples/declarative/tutorials/contacts/t8/contacts.qml
new file mode 100644
index 0000000..f76ccfd
--- /dev/null
+++ b/examples/declarative/tutorials/contacts/t8/contacts.qml
@@ -0,0 +1,133 @@
+<Rect id="Page" color="black" width="240" height="320">
+ <properties>
+ <Property name="listShown" value="1"/>
+ <Property name="mode" value="list"/>
+ <Property name="mouseGrabbed" value="false"/>
+ </properties>
+ <resources>
+ <SqlConnection id="contactDatabase" name="qmlConnection" driver="QSQLITE" databaseName="../shared/contacts.sqlite"/>
+ <SqlQuery id="contactList" connection="{contactDatabase}">
+ <query>SELECT recid, label, email, phone FROM contacts WHERE lower(label) LIKE lower(:searchTerm) ORDER BY label, recid</query>
+ <bindings>
+ <SqlBind name=":searchTerm" value="{searchBar.text + '%' }"/>
+ </bindings>
+ </SqlQuery>
+ <Component id="contactDelegate">
+ <Item id="wrapper" x="0" width="{ListView.view.width}" height="34">
+ <Text id="label" x="45" y="12" text="{model.label}" color="white" font.bold="true" width="{parent.width-30}" opacity="{listShown}"/>
+ <Item id="Details" anchors.fill="{wrapper}">
+ <Bind target="{Details.qmlItem}" property="contactid" value="{model.recid}"/>
+ <Bind target="{Details.qmlItem}" property="mode" value="{wrapper.state}"/>
+ <Bind target="{Details.qmlItem}" property="label" value="{model.label}"/>
+ <Bind target="{Details.qmlItem}" property="phone" value="{model.phone}"/>
+ <Bind target="{Details.qmlItem}" property="email" value="{model.email}"/>
+ </Item>
+ <MouseRegion anchors.fill="{label}" opacity="{listShown}">
+ <onClicked>
+ Details.qml = 'Contact.qml';
+ wrapper.state='opened';
+ </onClicked>
+ </MouseRegion>
+ <states>
+ <State name='opened'>
+ <SetProperty target="{wrapper}" property="height" value="{contactListView.height}"/>
+ <SetProperty target="{contactListView}" property="yPosition" value="{wrapper.y}"/>
+ <SetProperty target="{contactListView}" property="locked" value="1"/>
+ <SetProperty target="{Details.qmlItem}" property="mode" value="opened"/>
+ <SetProperty target="{Page}" property="mode" value="editExisting"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition>
+ <NumericAnimation duration="500" properties="yPosition,height,opacity"/>
+ </Transition>
+ </transitions>
+ <Connection sender="{confirmEditButton}" signal="clicked()">
+ if (Details.qmlItem.mode == 'opened' &amp;&amp; Page.mouseGrabbed != 'true') {
+ Details.qmlItem.mode = 'closed';
+ wrapper.state = "";
+ Details.qmlItem.confirm.emit();
+ }
+ </Connection>
+ <Connection sender="{cancelEditButton}" signal="clicked()">
+ if (Details.qmlItem.mode == 'opened' &amp;&amp; Page.mouseGrabbed != 'true') {
+ Details.qmlItem.mode = 'closed';
+ wrapper.state = "";
+ Details.qmlItem.cancel.emit();
+ }
+ </Connection>
+ </Item>
+ </Component>
+ </resources>
+ <Button id="newContactButton" icon="../shared/pics/new.png"
+ anchors.top="{parent.top}" anchors.topMargin="5"
+ anchors.right="{parent.right}" anchors.rightMargin="5"
+ onClicked="newContactItem.label = ''; newContactItem.phone = ''; newContactItem.email = ''; Page.mode = 'editNew'"
+ opacity="{Page.mode == 'list' ? 1 : 0}"/>
+ <Button id="cancelEditButton" icon="../shared/pics/cancel.png"
+ anchors.top="{parent.top}" anchors.topMargin="5"
+ anchors.right="{parent.right}" anchors.rightMargin="5"
+ opacity="{Page.mode == 'list' || Page.mouseGrabbed == 'true' ? 0 : 1}"/>
+ <Button id="confirmEditButton" icon="../shared/pics/ok.png"
+ anchors.top="{parent.top}" anchors.topMargin="5"
+ anchors.left="{parent.left}" anchors.leftMargin="5"
+ opacity="{Page.mode == 'list' || Page.mouseGrabbed == 'true' ? 0 : 1}"/>
+ <FocusRealm id="searchBarRealm"
+ height="30"
+ anchors.bottom="{parent.bottom}"
+ anchors.left="{parent.left}" anchors.right="{parent.right}"
+ focus="{Page.mode == 'list' ? 'true' : 'false'}">
+ <SearchBar id="searchBar" anchors.fill="{parent}">
+ <states>
+ <State name="searchHidden" when="{searchBar.text == '' || Page.listShown == 0}">
+ <SetProperty target="{searchBarRealm}" property="anchors.bottomMargin" value="-30"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="*">
+ <NumericAnimation property="bottomMargin" duration="250"/>
+ </Transition>
+ </transitions>
+ </SearchBar>
+ </FocusRealm>
+ <ListView id="contactListView" model="{contactList}" delegate="{contactDelegate}"
+ anchors.top="{newContactButton.bottom}" anchors.topMargin="10"
+ anchors.left="{parent.left}" anchors.right="{parent.right}"
+ anchors.bottom="{searchBarRealm.top}"
+ clip="true"
+ focus="{Page.mode == 'list' ? 'false' : 'true'}"
+ />
+ <Contact id="newContactItem"
+ mode="opened"
+ anchors.top="{newContactButton.bottom}" anchors.topMargin="10"
+ anchors.left="{parent.left}" anchors.right="{parent.right}"
+ anchors.bottom="{searchBarRealm.top}"
+ onClose="Page.mode='list'"
+ opacity="0"
+ />
+ <Connection sender="{confirmEditButton}" signal="clicked()">
+ if (Page.mode == 'editNew' &amp;&amp; Page.mouseGrabbed != 'true') {
+ newContactItem.confirm.emit()
+ }
+ </Connection>
+ <Connection sender="{cancelEditButton}" signal="clicked()">
+ if (Page.mode == 'editNew' &amp;&amp; Page.mouseGrabbed != 'true') {
+ newContactItem.cancel.emit()
+ }
+ </Connection>
+ <states>
+ <State name="editExistingState" when="{Page.mode == 'editExisting'}">
+ <SetProperty target="{Page}" property="listShown" value="0"/>
+ </State>
+ <State name="editNewState" when="{Page.mode == 'editNew'}">
+ <SetProperty target="{Page}" property="listShown" value="0"/>
+ <SetProperty target="{contactListView}" property="opacity" value="0"/>
+ <SetProperty target="{newContactItem}" property="opacity" value="1"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="*">
+ <NumericAnimation property="opacity" duration="500"/>
+ </Transition>
+ </transitions>
+</Rect>
diff --git a/examples/declarative/tutorials/t1/tutorial1.qml b/examples/declarative/tutorials/t1/tutorial1.qml
new file mode 100644
index 0000000..e4de571
--- /dev/null
+++ b/examples/declarative/tutorials/t1/tutorial1.qml
@@ -0,0 +1,3 @@
+<Rect id="Page" width="480" height="200" color="white">
+ <Text id="HelloText" text="Hello world!" font.size="24" font.bold="true" y="30" anchors.horizontalCenter="{Page.horizontalCenter}"/>
+</Rect>
diff --git a/examples/declarative/tutorials/t2/Cell.qml b/examples/declarative/tutorials/t2/Cell.qml
new file mode 100644
index 0000000..5d6ff52
--- /dev/null
+++ b/examples/declarative/tutorials/t2/Cell.qml
@@ -0,0 +1,7 @@
+<Item id="CellContainer" width="40" height="25">
+ <properties>
+ <Property name="color"/>
+ </properties>
+ <Rect anchors.fill="{parent}" color="{CellContainer.color}"/>
+ <MouseRegion anchors.fill="{parent}" onClicked="HelloText.color = CellContainer.color" />
+</Item>
diff --git a/examples/declarative/tutorials/t2/tutorial2.qml b/examples/declarative/tutorials/t2/tutorial2.qml
new file mode 100644
index 0000000..1e3af16
--- /dev/null
+++ b/examples/declarative/tutorials/t2/tutorial2.qml
@@ -0,0 +1,11 @@
+<Rect id="Page" width="480" height="200" color="white">
+ <Text id="HelloText" text="Hello world!" font.size="24" font.bold="true" y="30" anchors.horizontalCenter="{Page.horizontalCenter}"/>
+ <GridLayout id="ColorPicker" x="0" anchors.bottom="{Page.bottom}" width="120" height="50" columns="3" rows="2">
+ <Cell color="#ff0000"/>
+ <Cell color="#00ff00"/>
+ <Cell color="#0000ff"/>
+ <Cell color="#ffff00"/>
+ <Cell color="#00ffff"/>
+ <Cell color="#ff00ff"/>
+ </GridLayout>
+</Rect>
diff --git a/examples/declarative/tutorials/t3/Cell.qml b/examples/declarative/tutorials/t3/Cell.qml
new file mode 100644
index 0000000..5d6ff52
--- /dev/null
+++ b/examples/declarative/tutorials/t3/Cell.qml
@@ -0,0 +1,7 @@
+<Item id="CellContainer" width="40" height="25">
+ <properties>
+ <Property name="color"/>
+ </properties>
+ <Rect anchors.fill="{parent}" color="{CellContainer.color}"/>
+ <MouseRegion anchors.fill="{parent}" onClicked="HelloText.color = CellContainer.color" />
+</Item>
diff --git a/examples/declarative/tutorials/t3/tutorial3.qml b/examples/declarative/tutorials/t3/tutorial3.qml
new file mode 100644
index 0000000..f9f1415
--- /dev/null
+++ b/examples/declarative/tutorials/t3/tutorial3.qml
@@ -0,0 +1,27 @@
+<Rect id="Page" width="480" height="200" color="white">
+ <Text id="HelloText" text="Hello world!" font.size="24" font.bold="true" y="30" anchors.horizontalCenter="{Page.horizontalCenter}">
+ <states>
+ <State name="down" when="{MouseRegion.pressed == true}">
+ <SetProperty target="{HelloText}" property="y" value="160"/>
+ <SetProperty target="{HelloText}" property="color" value="red"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="down" reversible="true">
+ <ParallelAnimation>
+ <NumericAnimation properties="y" duration="500" easing="easeOutBounce"/>
+ <ColorAnimation duration="500"/>
+ </ParallelAnimation>
+ </Transition>
+ </transitions>
+ </Text>
+ <MouseRegion id="MouseRegion" anchors.fill="{HelloText}"/>
+ <GridLayout id="ColorPicker" x="0" anchors.bottom="{Page.bottom}" width="120" height="50" columns="3" rows="2">
+ <Cell color="#ff0000"/>
+ <Cell color="#00ff00"/>
+ <Cell color="#0000ff"/>
+ <Cell color="#ffff00"/>
+ <Cell color="#00ffff"/>
+ <Cell color="#ff00ff"/>
+ </GridLayout>
+</Rect>
diff --git a/examples/declarative/velocity/Day.qml b/examples/declarative/velocity/Day.qml
new file mode 100644
index 0000000..3441648
--- /dev/null
+++ b/examples/declarative/velocity/Day.qml
@@ -0,0 +1,41 @@
+<Rect width="400" height="500" radius="7" pen.color="black" id="Page">
+ <properties>
+ <Property name="day" type="string" />
+ <Property name="stickies" />
+ </properties>
+
+ <Image x="10" y="10" src="cork.jpg" opaque="true"/>
+ <Text x="20" y="20" height="40" font.size="14" font.bold="true" width="370" text="{day}" style="Outline" styleColor="#dedede"/>
+
+ <Repeater dataSource="{Page.stickies}">
+ <Item x="{Math.random() * 200 + 100}" y="{Math.random() * 300 + 50}" id="StickyPage">
+ <rotation>
+ <Follow source="{-Flick.xVelocity / 100}" spring="2.0" damping="0.1"/>
+ </rotation>
+ <Item id="Sticky" scale="0.5">
+ <Image id="StickyImage" src="sticky.png" smooth="true" y="-20" x="{8 + -width * 0.6 / 2}" scale="0.6" />
+ <TextEdit id="MyText" smooth="true" font.size="28" readOnly="false" x="-104" y="36" wrap="true" rotation="-8" text="{noteText}" width="195" height="172" />
+ <Item y="-20" x="{StickyImage.x}" width="{StickyImage.width * StickyImage.scale}" height="{StickyImage.height * StickyImage.scale}" >
+ <MouseRegion id="Mouse" onClicked="MyText.focus = true" anchors.fill="{parent}" drag.target="{StickyPage}" drag.axis="xy" drag.ymin="0" drag.ymax="500" drag.xmin="0" drag.xmax="400"/>
+ </Item>
+ </Item>
+ <Image src="tack.png" x="{-width / 2}" y="{-height * 0.7 / 2}" scale="0.7" />
+
+ <states>
+ <State name="pressed" when="{Mouse.pressed}">
+ <SetProperties target="{Sticky}" rotation="8" scale="1"/>
+ <SetProperties target="{Page}" z="8"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition>
+ <NumericAnimation properties="rotation,scale" duration="200"/>
+ </Transition>
+ </transitions>
+ </Item>
+ </Repeater>
+
+
+
+
+</Rect>
diff --git a/examples/declarative/velocity/cork.jpg b/examples/declarative/velocity/cork.jpg
new file mode 100644
index 0000000..d4d706c
--- /dev/null
+++ b/examples/declarative/velocity/cork.jpg
Binary files differ
diff --git a/examples/declarative/velocity/sticky.png b/examples/declarative/velocity/sticky.png
new file mode 100644
index 0000000..73df3cd
--- /dev/null
+++ b/examples/declarative/velocity/sticky.png
Binary files differ
diff --git a/examples/declarative/velocity/tack.png b/examples/declarative/velocity/tack.png
new file mode 100644
index 0000000..cef2d1c
--- /dev/null
+++ b/examples/declarative/velocity/tack.png
Binary files differ
diff --git a/examples/declarative/velocity/velocity.qml b/examples/declarative/velocity/velocity.qml
new file mode 100644
index 0000000..0215d37
--- /dev/null
+++ b/examples/declarative/velocity/velocity.qml
@@ -0,0 +1,81 @@
+<Rect color="lightSteelBlue" width="800" height="600">
+ <ListModel id="List">
+ <Day>
+ <name>Sunday</name>
+ <dayColor>#808080</dayColor>
+ <notes>
+ <Note noteText="Lunch" />
+ <Note noteText="Party" />
+ </notes>
+ </Day>
+ <Day>
+ <name>Monday</name>
+ <dayColor>blue</dayColor>
+ <notes>
+ <Note noteText="Pickup kids" />
+ <Note noteText="Checkout kinetic" />
+ <Note noteText="Read email" />
+ </notes>
+ </Day>
+ <Day>
+ <name>Tuesday</name>
+ <dayColor>yellow</dayColor>
+ <notes>
+ <Note noteText="Walk dog" />
+ <Note noteText="Buy newspaper" />
+ </notes>
+ </Day>
+ <Day>
+ <name>Wednesday</name>
+ <dayColor>purple</dayColor>
+ <notes>
+ <Note noteText="Cook dinner" />
+ <Note noteText="Eat dinner" />
+ </notes>
+ </Day>
+ <Day>
+ <name>Thursday</name>
+ <dayColor>blue</dayColor>
+ <notes>
+ <Note noteText="5:30pm Meeting" />
+ <Note noteText="Weed garden" />
+ </notes>
+ </Day>
+ <Day>
+ <name>Friday</name>
+ <dayColor>green</dayColor>
+ <notes>
+ <Note noteText="Still work" />
+ <Note noteText="Drink" />
+ </notes>
+ </Day>
+ <Day>
+ <name>Saturday</name>
+ <dayColor>orange</dayColor>
+ <notes>
+ <Note noteText="Drink" />
+ <Note noteText="Drink" />
+ </notes>
+ </Day>
+ </ListModel>
+
+ <Flickable id="Flick" anchors.fill="{parent}" viewportWidth="{Lay.width}">
+ <HorizontalLayout id="Lay">
+ <Repeater dataSource="{List}">
+ <Component>
+ <Day day="{name}" color="{dayColor}" stickies="{notes}"/>
+ </Component>
+ </Repeater>
+ <!--
+ <Day color="#808080" day="Sunday" />
+ <Day color="blue" day="Monday"/>
+ <Day color="yellow" day="Tuesday"/>
+ <Day color="purple" day="Wednesday"/>
+ <Day color="blue" day="Thursday"/>
+ <Day color="green" day="Friday"/>
+ <Day color="orange" day="Saturday"/>
+ -->
+ </HorizontalLayout>
+ </Flickable>
+
+</Rect>
diff --git a/examples/declarative/webview/autosize.qml b/examples/declarative/webview/autosize.qml
new file mode 100644
index 0000000..fedd497
--- /dev/null
+++ b/examples/declarative/webview/autosize.qml
@@ -0,0 +1,42 @@
+<!-- The WebView size is determined by the width, height,
+ idealWidth, and idealHeight properties. -->
+<Rect id="Rect" color="white" width="200" height="{Layout.height}">
+ <VerticalLayout id="Layout" spacing="2">
+ <WebView>
+ <html><![CDATA[
+ No width defined.
+ ]]></html>
+ <Rect color="#10000000" anchors.fill="{parent}"/>
+ </WebView>
+ <WebView width="{Rect.width}">
+ <html><![CDATA[
+ The width is full.
+ ]]></html>
+ <Rect color="#10000000" anchors.fill="{parent}"/>
+ </WebView>
+ <WebView width="{Rect.width/2}">
+ <html><![CDATA[
+ The width is half.
+ ]]></html>
+ <Rect color="#10000000" anchors.fill="{parent}"/>
+ </WebView>
+ <WebView idealWidth="{Rect.width/2}">
+ <html><![CDATA[
+ The idealWidth is half.
+ ]]></html>
+ <Rect color="#10000000" anchors.fill="{parent}"/>
+ </WebView>
+ <WebView idealWidth="{Rect.width/2}">
+ <html><![CDATA[
+ The_idealWidth_is_half.
+ ]]></html>
+ <Rect color="#10000000" anchors.fill="{parent}"/>
+ </WebView>
+ <WebView width="{Rect.width/2}">
+ <html><![CDATA[
+ The_width_is_half.
+ ]]></html>
+ <Rect color="#10000000" anchors.fill="{parent}"/>
+ </WebView>
+ </VerticalLayout>
+</Rect>
diff --git a/examples/declarative/webview/content/SpinSquare.qml b/examples/declarative/webview/content/SpinSquare.qml
new file mode 100644
index 0000000..ced45d5
--- /dev/null
+++ b/examples/declarative/webview/content/SpinSquare.qml
@@ -0,0 +1,12 @@
+<Item id="Root">
+ <properties>
+ <Property name="period" value="250"/>
+ <Property name="color" value="black"/>
+ </properties>
+ <Item x="{Root.width/2}" y="{Root.height/2}">
+ <Rect color="{Root.color}" width="{Root.width}" height="{width}" x="{-width/2}" y="{-height/2}"/>
+ <rotation>
+ <NumericAnimation from="0" to="360" repeat="true" running="true" duration="{Root.period}"/>
+ </rotation>
+ </Item>
+</Item>
diff --git a/examples/declarative/webview/inline-html.qml b/examples/declarative/webview/inline-html.qml
new file mode 100644
index 0000000..701db41
--- /dev/null
+++ b/examples/declarative/webview/inline-html.qml
@@ -0,0 +1,13 @@
+<!-- Inline HTML with loose formatting can be
+ set on the html property by using CDATA. -->
+<WebView>
+ <html><![CDATA[
+ <body bgcolor="white">
+ <table border=1>
+ <tr><th><th>One<th>Two<th>Three
+ <tr><th>1<td>X<td>1<td>X
+ <tr><th>2<td>0<td>X<td>0
+ <tr><th>3<td>X<td>1<td>X
+ </table>
+ ]]></html>
+</WebView>
diff --git a/examples/declarative/webview/inline-xhtml.qml b/examples/declarative/webview/inline-xhtml.qml
new file mode 100644
index 0000000..4acb417
--- /dev/null
+++ b/examples/declarative/webview/inline-xhtml.qml
@@ -0,0 +1,14 @@
+<!-- Inline xHTML (with strict XML formatting) can be
+ set on the html property by giving it the appropriate namespace. -->
+<WebView>
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <body bgcolor="white">
+ <table border="1">
+ <tr><th></th><th>One</th><th>Two</th><th>Three</th></tr>
+ <tr><th>1</th><td>X</td><td>1</td><td>X</td></tr>
+ <tr><th>2</th><td>0</td><td>X</td><td>0</td></tr>
+ <tr><th>3</th><td>X</td><td>1</td><td>X</td></tr>
+ </table>
+ </body>
+ </html>
+</WebView>
diff --git a/examples/declarative/webview/qml-in-html.qml b/examples/declarative/webview/qml-in-html.qml
new file mode 100644
index 0000000..2715788
--- /dev/null
+++ b/examples/declarative/webview/qml-in-html.qml
@@ -0,0 +1,20 @@
+<!-- The WebView supports QML data through the HTML OBJECT tag -->
+<Flickable width="{250*.75}" height="240"
+ viewportWidth="{Web.width*Web.scale}" viewportHeight="{Web.height*Web.scale}">
+<WebView id="Web" width="250" height="420" scale="0.75">
+ <html><![CDATA[
+ <html>
+ <body bgcolor=white>
+ These are QML plugins, shown in a QML WebView via HTML OBJECT tags, all scaled to 75%
+ and placed in a Flickable area...
+ <table border=1>
+ <tr><th>Duration <th>Color <th>Plugin
+ <tr><td>500 <td>red <td><OBJECT data=content/SpinSquare.qml TYPE=application/x-qt-plugin width=100 height=100 period=500 color=red />
+ <tr><td>2000 <td>blue <td><OBJECT data=content/SpinSquare.qml TYPE=application/x-qt-plugin width=100 height=100 period=2000 color=blue />
+ <tr><td>1000 <td>green <td><OBJECT data=content/SpinSquare.qml TYPE=application/x-qt-plugin width=100 height=100 period=1000 color=green />
+ </table>
+ </body>
+ </html>
+ ]]></html>
+</WebView>
+</Flickable>
diff --git a/examples/declarative/webview/transparent.qml b/examples/declarative/webview/transparent.qml
new file mode 100644
index 0000000..71e1621
--- /dev/null
+++ b/examples/declarative/webview/transparent.qml
@@ -0,0 +1,6 @@
+<!-- The WebView background is transparent
+ if the HTML does not specify a background -->
+
+<Rect color="green" width="{Web.width}" height="{Web.height}">
+ <WebView id="Web" html="Hello &lt;b&gt;World!&lt;/b&gt;"/>
+</Rect>
diff --git a/examples/declarative/xmldata/daringfireball.qml b/examples/declarative/xmldata/daringfireball.qml
new file mode 100644
index 0000000..cfd0a98
--- /dev/null
+++ b/examples/declarative/xmldata/daringfireball.qml
@@ -0,0 +1,25 @@
+<Rect color="white" width="600" height="600">
+ <resources>
+ <XmlListModel id="feedModel" src="http://daringfireball.net/index.xml"
+ query="doc($src)/feed/entry">
+ <namespaceDeclarations>
+ declare default element namespace 'http://www.w3.org/2005/Atom';
+ </namespaceDeclarations>
+ <Role name="title" query="title/string()"/>
+ <Role name="tagline" query="author/name/string()"/>
+ <Role name="content" query="content/string()" isCData="true"/>
+ </XmlListModel>
+ <Component id="feedDelegate">
+ <Item height="{contents.height + 20}">
+ <Text x="10" id="TitleText" text="{title}" font.bold="true"/>
+ <Text text="{'by ' + tagline}" anchors.left="{TitleText.right}" anchors.leftMargin="10" font.italic="true"/>
+ <Text x="10" text="{content}" anchors.top="{TitleText.bottom}" width="580" wrap="true">
+ <onLinkActivated>print('link clicked: ' + link)</onLinkActivated>
+ </Text>
+ </Item>
+ </Component>
+ </resources>
+
+ <ListView id="list" anchors.fill="{parent}" clip="true"
+ model="{feedModel}" delegate="{feedDelegate}"/>
+</Rect>
diff --git a/examples/declarative/xmldata/yahoonews.qml b/examples/declarative/xmldata/yahoonews.qml
new file mode 100644
index 0000000..80ace18
--- /dev/null
+++ b/examples/declarative/xmldata/yahoonews.qml
@@ -0,0 +1,38 @@
+<Rect color="black" gradientColor="#AAAAAA" width="600" height="600">
+ <resources>
+ <XmlListModel id="feedModel" src="http://rss.news.yahoo.com/rss/oceania" query="doc($src)/rss/channel/item">
+ <Role name="title" query="title/string()"/>
+ <Role name="link" query="link/string()"/>
+ <Role name="description" query="description/string()" isCData="true"/>
+ </XmlListModel>
+ <Component id="feedDelegate">
+ <Item id="Delegate" height="{Wrapper.height + 10}">
+ <MouseRegion anchors.fill="{Wrapper}" onPressed="Delegate.ListView.list.currentIndex = index;"
+ onClicked="if (Wrapper.state == 'Details') { Wrapper.state = '';} else {Wrapper.state = 'Details';}"/>
+ <Rect id="Wrapper" y="5" height="{TitleText.height + 10}" width="580" color="#F0F0F0" radius="5">
+ <Text x="10" y="5" id="TitleText" text="{'&lt;a href=\'' + link + '\'&gt;' + title + '&lt;/a&gt;'}" font.bold="true" font.family="Helvetica" font.size="14" onLinkActivated="print('link clicked: ' + link)"/>
+ <Text x="10" id="Description" text="{description}" width="560" wrap="true" font.family="Helvetica"
+ anchors.top="{TitleText.bottom}" anchors.topMargin="5" opacity="0"/>
+
+ <states>
+ <State name="Details">
+ <SetProperty target="{Wrapper}" property="height" binding="contents.height + 10"/>
+ <SetProperty target="{Description}" property="opacity" value="1"/>
+ </State>
+ </states>
+ <transitions>
+ <Transition fromState="*" toState="Details" reversible="true">
+ <SequentialAnimation>
+ <NumericAnimation duration="200" properties="height" easing="easeOutQuad"/>
+ <NumericAnimation duration="200" properties="opacity"/>
+ </SequentialAnimation>
+ </Transition>
+ </transitions>
+ </Rect>
+ </Item>
+ </Component>
+ </resources>
+
+ <ListView id="list" x="10" y="10" width="{parent.width - 20}" height="{parent.height - 20}" clip="true"
+ model="{feedModel}" delegate="{feedDelegate}" currentItemPositioning="Snap"/>
+</Rect>
diff --git a/examples/examples.pro b/examples/examples.pro
index 2c4fc81..874cd37 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -14,16 +14,19 @@ SUBDIRS = \
qtconcurrent \
richtext \
sql \
+ statemachine \
threads \
tools \
tutorials \
widgets \
uitools \
+ declarative \
xml \
script
contains(QT_CONFIG, phonon):!static: SUBDIRS += phonon
contains(QT_CONFIG, webkit): SUBDIRS += webkit
+contains(QT_CONFIG, animation): SUBDIRS += animation
embedded:SUBDIRS += qws
!wince*: {
!contains(QT_EDITION, Console):contains(QT_BUILD_PARTS, tools):SUBDIRS += designer
diff --git a/examples/opengl/hellogl_es2/glwidget.cpp b/examples/opengl/hellogl_es2/glwidget.cpp
index 213c5b2..ee50670 100644
--- a/examples/opengl/hellogl_es2/glwidget.cpp
+++ b/examples/opengl/hellogl_es2/glwidget.cpp
@@ -48,124 +48,10 @@
const int bubbleNum = 8;
-inline void CrossProduct(qreal &xOut, qreal &yOut, qreal &zOut, qreal x1, qreal y1, qreal z1, qreal x2, qreal y2, qreal z2)
-{
- xOut = y1 * z2 - z1 * y2;
- yOut = z1 * x2 - x1 * z2;
- zOut = x1 * y2 - y1 * x2;
-}
-
-inline void Normalize(qreal &x, qreal &y, qreal &z)
-{
- qreal l = sqrt(x*x + y*y + z*z);
- x = x / l;
- y = y / l;
- z = z / l;
-}
-
-inline void IdentityMatrix(GLfloat *m)
-{
- m[0 * 4 + 0] = 1.0f;
- m[1 * 4 + 0] = 0.0f;
- m[2 * 4 + 0] = 0.0f;
- m[3 * 4 + 0] = 0.0f;
- m[0 * 4 + 1] = 0.0f;
- m[1 * 4 + 1] = 1.0f;
- m[2 * 4 + 1] = 0.0f;
- m[3 * 4 + 1] = 0.0f;
- m[0 * 4 + 2] = 0.0f;
- m[1 * 4 + 2] = 0.0f;
- m[2 * 4 + 2] = 1.0f;
- m[3 * 4 + 2] = 0.0f;
- m[0 * 4 + 3] = 0.0f;
- m[1 * 4 + 3] = 0.0f;
- m[2 * 4 + 3] = 0.0f;
- m[3 * 4 + 3] = 1.0f;
-}
-
-// Adjust a 4x4 matrix to apply a scale.
-inline void ScaleMatrix(GLfloat *m, GLfloat scalex, GLfloat scaley, GLfloat scalez)
-{
- m[0 * 4 + 0] *= scalex;
- m[0 * 4 + 1] *= scalex;
- m[0 * 4 + 2] *= scalex;
- m[0 * 4 + 3] *= scalex;
- m[1 * 4 + 0] *= scaley;
- m[1 * 4 + 1] *= scaley;
- m[1 * 4 + 2] *= scaley;
- m[1 * 4 + 3] *= scaley;
- m[2 * 4 + 0] *= scalez;
- m[2 * 4 + 1] *= scalez;
- m[2 * 4 + 2] *= scalez;
- m[2 * 4 + 3] *= scalez;
-}
-
-// Adjust a 4x4 matrix to apply a translation.
-inline void TranslateMatrix(GLfloat *m, GLfloat translatex, GLfloat translatey, GLfloat translatez)
-{
- m[3 * 4 + 0] += m[0 * 4 + 0] * translatex + m[1 * 4 + 0] * translatey + m[2 * 4 + 0] * translatez;
- m[3 * 4 + 1] += m[0 * 4 + 1] * translatex + m[1 * 4 + 1] * translatey + m[2 * 4 + 1] * translatez;
- m[3 * 4 + 2] += m[0 * 4 + 2] * translatex + m[1 * 4 + 2] * translatey + m[2 * 4 + 2] * translatez;
- m[3 * 4 + 3] += m[0 * 4 + 3] * translatex + m[1 * 4 + 3] * translatey + m[2 * 4 + 3] * translatez;
-}
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-// Adjust a 4x4 matrix to apply a rotation.
-inline void RotateMatrix(GLfloat *m, GLfloat angle, GLfloat vx, GLfloat vy, GLfloat vz)
-{
- GLfloat len = sqrt(vx * vx + vy * vy + vz * vz);
- if (len != 0) {
- vx /= len;
- vy /= len;
- vz /= len;
- }
-
- GLfloat c, s, ic;
- c = cos(angle * M_PI / 180.0);
- s = sin(angle * M_PI / 180.0);
- ic = 1.0f - c;
-
- GLfloat rot[16];
- rot[0 * 4 + 0] = vx * vx * ic + c;
- rot[1 * 4 + 0] = vx * vy * ic - vz * s;
- rot[2 * 4 + 0] = vx * vz * ic + vy * s;
- rot[3 * 4 + 0] = 0.0f;
- rot[0 * 4 + 1] = vy * vx * ic + vz * s;
- rot[1 * 4 + 1] = vy * vy * ic + c;
- rot[2 * 4 + 1] = vy * vz * ic - vx * s;
- rot[3 * 4 + 1] = 0.0f;
- rot[0 * 4 + 2] = vx * vz * ic - vy * s;
- rot[1 * 4 + 2] = vy * vz * ic + vx * s;
- rot[2 * 4 + 2] = vz * vz * ic + c;
- rot[3 * 4 + 2] = 0.0f;
- rot[0 * 4 + 3] = 0.0f;
- rot[1 * 4 + 3] = 0.0f;
- rot[2 * 4 + 3] = 0.0f;
- rot[3 * 4 + 3] = 1.0f;
-
- GLfloat temp[16];
- for (int i = 0; i < 4; ++i) {
- for (int j = 0; j < 4; ++j) {
- temp[j * 4 + i] = 0.0f;
- for (int k = 0; k < 4; ++k) {
- temp[j * 4 + i] += m[k * 4 + i] * rot[j * 4 + k];
- }
- }
- }
-
- qMemCopy(m, temp, sizeof(temp));
-}
-
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(parent)
{
qtLogo = true;
- createdVertices = 0;
- createdNormals = 0;
- m_vertexNumber = 0;
frames = 0;
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground);
@@ -178,10 +64,6 @@ GLWidget::GLWidget(QWidget *parent)
GLWidget::~GLWidget()
{
- if (createdVertices)
- delete[] createdVertices;
- if (createdNormals)
- delete[] createdNormals;
}
void GLWidget::setScaling(int scale) {
@@ -210,13 +92,11 @@ void GLWidget::showBubbles(bool bubbles)
void GLWidget::paintQtLogo()
{
glDisable(GL_TEXTURE_2D);
- glVertexAttribPointer(vertexAttr1, 3, GL_FLOAT, GL_FALSE, 0, createdVertices);
- glEnableVertexAttribArray(vertexAttr1);
- glVertexAttribPointer(normalAttr1, 3, GL_FLOAT, GL_FALSE, 0, createdNormals);
- glEnableVertexAttribArray(normalAttr1);
- glDrawArrays(GL_TRIANGLES, 0, m_vertexNumber / 3);
- glDisableVertexAttribArray(normalAttr1);
- glDisableVertexAttribArray(vertexAttr1);
+ program1.setAttributeArray(vertexAttr1, vertices.constData());
+ program1.setAttributeArray(normalAttr1, normals.constData());
+ glDrawArrays(GL_TRIANGLES, 0, vertices.size());
+ program1.disableAttributeArray(normalAttr1);
+ program1.disableAttributeArray(vertexAttr1);
}
void GLWidget::paintTexturedCube()
@@ -239,8 +119,7 @@ void GLWidget::paintTexturedCube()
-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5,
0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5
};
- glVertexAttribPointer(vertexAttr2, 3, GL_FLOAT, GL_FALSE, 0, afVertices);
- glEnableVertexAttribArray(vertexAttr2);
+ program2.setAttributeArray(vertexAttr2, afVertices, 3);
GLfloat afTexCoord[] = {
0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
@@ -258,8 +137,7 @@ void GLWidget::paintTexturedCube()
1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f,
0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f
};
- glVertexAttribPointer(texCoordAttr2, 2, GL_FLOAT, GL_FALSE, 0, afTexCoord);
- glEnableVertexAttribArray(texCoordAttr2);
+ program2.setAttributeArray(texCoordAttr2, afTexCoord, 2);
GLfloat afNormals[] = {
@@ -278,50 +156,15 @@ void GLWidget::paintTexturedCube()
0,1,0, 0,1,0, 0,1,0,
0,1,0, 0,1,0, 0,1,0
};
- glVertexAttribPointer(normalAttr2, 3, GL_FLOAT, GL_FALSE, 0, afNormals);
- glEnableVertexAttribArray(normalAttr2);
+ program2.setAttributeArray(normalAttr2, afNormals, 3);
- glUniform1i(textureUniform2, 0); // use texture unit 0
+ program2.setUniformValue(textureUniform2, 0); // use texture unit 0
glDrawArrays(GL_TRIANGLES, 0, 36);
- glDisableVertexAttribArray(vertexAttr2);
- glDisableVertexAttribArray(normalAttr2);
- glDisableVertexAttribArray(texCoordAttr2);
-}
-
-static void reportCompileErrors(GLuint shader, const char *src)
-{
- GLint value = 0;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
- bool compiled = (value != 0);
- value = 0;
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value);
- if (!compiled && value > 1) {
- char *log = new char [value];
- GLint len;
- glGetShaderInfoLog(shader, value, &len, log);
- qWarning("%s\n", log);
- qWarning("when compiling:\n%s\n", src);
- delete [] log;
- }
-}
-
-static void reportLinkErrors(GLuint program, const char *vsrc, const char *fsrc)
-{
- GLint value = 0;
- glGetProgramiv(program, GL_LINK_STATUS, &value);
- bool linked = (value != 0);
- value = 0;
- glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value);
- if (!linked && value > 1) {
- char *log = new char [value];
- GLint len;
- glGetProgramInfoLog(program, value, &len, log);
- qWarning("%s\n", log);
- qWarning("when linking:\n%s\nwith:\n%s\n", vsrc, fsrc);
- delete [] log;
- }
+ program2.disableAttributeArray(vertexAttr2);
+ program2.disableAttributeArray(normalAttr2);
+ program2.disableAttributeArray(texCoordAttr2);
}
void GLWidget::initializeGL ()
@@ -332,8 +175,8 @@ void GLWidget::initializeGL ()
glGenTextures(1, &m_uiTexture);
m_uiTexture = bindTexture(QImage(":/qt.png"));
- GLuint vshader1 = glCreateShader(GL_VERTEX_SHADER);
- const char *vsrc1[1] = {
+ QGLShader *vshader1 = new QGLShader(QGLShader::VertexShader, this);
+ const char *vsrc1 =
"attribute highp vec4 vertex;\n"
"attribute mediump vec3 normal;\n"
"uniform mediump mat4 matrix;\n"
@@ -346,36 +189,28 @@ void GLWidget::initializeGL ()
" color = vec4(col * 0.2 + col * 0.8 * angle, 1.0);\n"
" color = clamp(color, 0.0, 1.0);\n"
" gl_Position = matrix * vertex;\n"
- "}\n"
- };
- glShaderSource(vshader1, 1, vsrc1, 0);
- glCompileShader(vshader1);
- reportCompileErrors(vshader1, vsrc1[0]);
+ "}\n";
+ vshader1->setSourceCode(vsrc1);
- GLuint fshader1 = glCreateShader(GL_FRAGMENT_SHADER);
- const char *fsrc1[1] = {
+ QGLShader *fshader1 = new QGLShader(QGLShader::FragmentShader, this);
+ const char *fsrc1 =
"varying mediump vec4 color;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = color;\n"
- "}\n"
- };
- glShaderSource(fshader1, 1, fsrc1, 0);
- glCompileShader(fshader1);
- reportCompileErrors(fshader1, fsrc1[0]);
-
- program1 = glCreateProgram();
- glAttachShader(program1, vshader1);
- glAttachShader(program1, fshader1);
- glLinkProgram(program1);
- reportLinkErrors(program1, vsrc1[0], fsrc1[0]);
-
- vertexAttr1 = glGetAttribLocation(program1, "vertex");
- normalAttr1 = glGetAttribLocation(program1, "normal");
- matrixUniform1 = glGetUniformLocation(program1, "matrix");
-
- GLuint vshader2 = glCreateShader(GL_VERTEX_SHADER);
- const char *vsrc2[1] = {
+ "}\n";
+ fshader1->setSourceCode(fsrc1);
+
+ program1.addShader(vshader1);
+ program1.addShader(fshader1);
+ program1.link();
+
+ vertexAttr1 = program1.attributeLocation("vertex");
+ normalAttr1 = program1.attributeLocation("normal");
+ matrixUniform1 = program1.uniformLocation("matrix");
+
+ QGLShader *vshader2 = new QGLShader(QGLShader::VertexShader);
+ const char *vsrc2 =
"attribute highp vec4 vertex;\n"
"attribute highp vec4 texCoord;\n"
"attribute mediump vec3 normal;\n"
@@ -388,14 +223,11 @@ void GLWidget::initializeGL ()
" angle = max(dot(normal, toLight), 0.0);\n"
" gl_Position = matrix * vertex;\n"
" texc = texCoord;\n"
- "}\n"
- };
- glShaderSource(vshader2, 1, vsrc2, 0);
- glCompileShader(vshader2);
- reportCompileErrors(vshader2, vsrc2[0]);
+ "}\n";
+ vshader2->setSourceCode(vsrc2);
- GLuint fshader2 = glCreateShader(GL_FRAGMENT_SHADER);
- const char *fsrc2[1] = {
+ QGLShader *fshader2 = new QGLShader(QGLShader::FragmentShader);
+ const char *fsrc2 =
"varying highp vec4 texc;\n"
"uniform sampler2D tex;\n"
"varying mediump float angle;\n"
@@ -404,23 +236,18 @@ void GLWidget::initializeGL ()
" highp vec3 color = texture2D(tex, texc.st).rgb;\n"
" color = color * 0.2 + color * 0.8 * angle;\n"
" gl_FragColor = vec4(clamp(color, 0.0, 1.0), 1.0);\n"
- "}\n"
- };
- glShaderSource(fshader2, 1, fsrc2, 0);
- glCompileShader(fshader2);
- reportCompileErrors(fshader2, fsrc2[0]);
-
- program2 = glCreateProgram();
- glAttachShader(program2, vshader2);
- glAttachShader(program2, fshader2);
- glLinkProgram(program2);
- reportLinkErrors(program2, vsrc2[0], fsrc2[0]);
-
- vertexAttr2 = glGetAttribLocation(program2, "vertex");
- normalAttr2 = glGetAttribLocation(program2, "normal");
- texCoordAttr2 = glGetAttribLocation(program2, "texCoord");
- matrixUniform2 = glGetUniformLocation(program2, "matrix");
- textureUniform2 = glGetUniformLocation(program2, "tex");
+ "}\n";
+ fshader2->setSourceCode(fsrc2);
+
+ program2.addShader(vshader2);
+ program2.addShader(fshader2);
+ program2.link();
+
+ vertexAttr2 = program2.attributeLocation("vertex");
+ normalAttr2 = program2.attributeLocation("normal");
+ texCoordAttr2 = program2.attributeLocation("texCoord");
+ matrixUniform2 = program2.uniformLocation("matrix");
+ textureUniform2 = program2.uniformLocation("tex");
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -450,24 +277,23 @@ void GLWidget::paintGL()
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
- GLfloat modelview[16];
- IdentityMatrix(modelview);
- RotateMatrix(modelview, m_fAngle, 0.0, 1.0, 0.0);
- RotateMatrix(modelview, m_fAngle, 1.0, 0.0, 0.0);
- RotateMatrix(modelview, m_fAngle, 0.0, 0.0, 1.0);
- ScaleMatrix(modelview, m_fScale, m_fScale, m_fScale);
- TranslateMatrix(modelview, 0, -0.2, 0);
+ QMatrix4x4 modelview;
+ modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f);
+ modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f);
+ modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f);
+ modelview.scale(m_fScale);
+ modelview.translate(0.0f, -0.2f, 0.0f);
if (qtLogo) {
- glUseProgram(program1);
- glUniformMatrix4fv(matrixUniform1, 1, GL_FALSE, modelview);
+ program1.enable();
+ program1.setUniformValue(matrixUniform1, modelview);
paintQtLogo();
- glUseProgram(0);
+ program1.disable();
} else {
- glUseProgram(program2);
- glUniformMatrix4fv(matrixUniform2, 1, GL_FALSE, modelview);
+ program2.enable();
+ program1.setUniformValue(matrixUniform2, modelview);
paintTexturedCube();
- glUseProgram(0);
+ program2.disable();
}
glDisable(GL_DEPTH_TEST);
@@ -563,80 +389,69 @@ void GLWidget::createGeometry()
extrude(x8, y8, x5, y5);
}
- m_vertexNumber = vertices.size();
- createdVertices = new GLfloat[m_vertexNumber];
- createdNormals = new GLfloat[m_vertexNumber];
- for (int i = 0;i < m_vertexNumber;i++) {
- createdVertices[i] = vertices.at(i) * 2;
- createdNormals[i] = normals.at(i);
- }
- vertices.clear();
- normals.clear();
+ for (int i = 0;i < vertices.size();i++)
+ vertices[i] *= 2.0f;
}
void GLWidget::quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4)
{
- qreal nx, ny, nz;
+ vertices << QVector3D(x1, y1, -0.05f);
+ vertices << QVector3D(x2, y2, -0.05f);
+ vertices << QVector3D(x4, y4, -0.05f);
- vertices << x1 << y1 << -0.05f;
- vertices << x2 << y2 << -0.05f;
- vertices << x4 << y4 << -0.05f;
+ vertices << QVector3D(x3, y3, -0.05f);
+ vertices << QVector3D(x4, y4, -0.05f);
+ vertices << QVector3D(x2, y2, -0.05f);
- vertices << x3 << y3 << -0.05f;
- vertices << x4 << y4 << -0.05f;
- vertices << x2 << y2 << -0.05f;
+ QVector3D n = QVector3D::normal
+ (QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(x4 - x1, y4 - y1, 0.0f));
- CrossProduct(nx, ny, nz, x2 - x1, y2 - y1, 0, x4 - x1, y4 - y1, 0);
- Normalize(nx, ny, nz);
+ normals << n;
+ normals << n;
+ normals << n;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
+ normals << n;
+ normals << n;
+ normals << n;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
+ vertices << QVector3D(x4, y4, 0.05f);
+ vertices << QVector3D(x2, y2, 0.05f);
+ vertices << QVector3D(x1, y1, 0.05f);
- vertices << x4 << y4 << 0.05f;
- vertices << x2 << y2 << 0.05f;
- vertices << x1 << y1 << 0.05f;
+ vertices << QVector3D(x2, y2, 0.05f);
+ vertices << QVector3D(x4, y4, 0.05f);
+ vertices << QVector3D(x3, y3, 0.05f);
- vertices << x2 << y2 << 0.05f;
- vertices << x4 << y4 << 0.05f;
- vertices << x3 << y3 << 0.05f;
+ n = QVector3D::normal
+ (QVector3D(x2 - x4, y2 - y4, 0.0f), QVector3D(x1 - x4, y1 - y4, 0.0f));
- CrossProduct(nx, ny, nz, x2 - x4, y2 - y4, 0, x1 - x4, y1 - y4, 0);
- Normalize(nx, ny, nz);
+ normals << n;
+ normals << n;
+ normals << n;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
-
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
+ normals << n;
+ normals << n;
+ normals << n;
}
void GLWidget::extrude(qreal x1, qreal y1, qreal x2, qreal y2)
{
- qreal nx, ny, nz;
-
- vertices << x1 << y1 << +0.05f;
- vertices << x2 << y2 << +0.05f;
- vertices << x1 << y1 << -0.05f;
+ vertices << QVector3D(x1, y1, +0.05f);
+ vertices << QVector3D(x2, y2, +0.05f);
+ vertices << QVector3D(x1, y1, -0.05f);
- vertices << x2 << y2 << -0.05f;
- vertices << x1 << y1 << -0.05f;
- vertices << x2 << y2 << +0.05f;
+ vertices << QVector3D(x2, y2, -0.05f);
+ vertices << QVector3D(x1, y1, -0.05f);
+ vertices << QVector3D(x2, y2, +0.05f);
- CrossProduct(nx, ny, nz, x2 - x1, y2 - y1, 0.0f, 0.0f, 0.0f, -0.1f);
- Normalize(nx, ny, nz);
+ QVector3D n = QVector3D::normal
+ (QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(0.0f, 0.0f, -0.1f));
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
+ normals << n;
+ normals << n;
+ normals << n;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
- normals << nx << ny << nz;
+ normals << n;
+ normals << n;
+ normals << n;
}
diff --git a/examples/opengl/hellogl_es2/glwidget.h b/examples/opengl/hellogl_es2/glwidget.h
index 9a7823a..596e1cc 100644
--- a/examples/opengl/hellogl_es2/glwidget.h
+++ b/examples/opengl/hellogl_es2/glwidget.h
@@ -43,7 +43,11 @@
#define GLWIDGET_H
#include <QGLWidget>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtOpenGL/qglshaderprogram.h>
#include <QTime>
+#include <QVector>
class Bubble;
class GLWidget : public QGLWidget {
@@ -71,24 +75,21 @@ private:
void createBubbles(int number);
void quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4);
void extrude(qreal x1, qreal y1, qreal x2, qreal y2);
- QList<qreal> vertices;
- QList<qreal> normals;
- GLfloat *createdVertices;
- GLfloat *createdNormals;
- int m_vertexNumber;
+ QVector<QVector3D> vertices;
+ QVector<QVector3D> normals;
bool qtLogo;
QList<Bubble*> bubbles;
int frames;
QTime time;
- GLuint program1;
- GLuint program2;
- GLuint vertexAttr1;
- GLuint normalAttr1;
- GLuint matrixUniform1;
- GLuint vertexAttr2;
- GLuint normalAttr2;
- GLuint texCoordAttr2;
- GLuint matrixUniform2;
- GLuint textureUniform2;
+ QGLShaderProgram program1;
+ QGLShaderProgram program2;
+ int vertexAttr1;
+ int normalAttr1;
+ int matrixUniform1;
+ int vertexAttr2;
+ int normalAttr2;
+ int texCoordAttr2;
+ int matrixUniform2;
+ int textureUniform2;
};
#endif
diff --git a/examples/statemachine/README b/examples/statemachine/README
new file mode 100644
index 0000000..2879e67
--- /dev/null
+++ b/examples/statemachine/README
@@ -0,0 +1,36 @@
+Qt is provided with a powerful hierchical finite state machine through
+the Qt State Machine classes.
+
+The example launcher provided with Qt can be used to explore each of the
+examples in this directory.
+
+Documentation for these examples can be found via the Tutorial and Examples
+link in the main Qt documentation.
+
+
+Finding the Qt Examples and Demos launcher
+==========================================
+
+On Windows:
+
+The launcher can be accessed via the Windows Start menu. Select the menu
+entry entitled "Qt Examples and Demos" entry in the submenu containing
+the Qt tools.
+
+On Mac OS X:
+
+For the binary distribution, the qtdemo executable is installed in the
+/Developer/Applications/Qt directory. For the source distribution, it is
+installed alongside the other Qt tools on the path specified when Qt is
+configured.
+
+On Unix/Linux:
+
+The qtdemo executable is installed alongside the other Qt tools on the path
+specified when Qt is configured.
+
+On all platforms:
+
+The source code for the launcher can be found in the demos/qtdemo directory
+in the Qt package. This example is built at the same time as the Qt libraries,
+tools, examples, and demonstrations.
diff --git a/examples/statemachine/citizenquartz/citizenquartz.pro b/examples/statemachine/citizenquartz/citizenquartz.pro
new file mode 100644
index 0000000..58039a0
--- /dev/null
+++ b/examples/statemachine/citizenquartz/citizenquartz.pro
@@ -0,0 +1,20 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp \
+ clock.cpp \
+ clockbutton.cpp \
+ clockdisplay.cpp \
+ propertyaddstate.cpp \
+
+HEADERS += clock.h \
+ clockbutton.h \
+ clockdisplay.h \
+ propertyaddstate.h \
+ timeperiod.h \
+
+RESOURCES += citizenquartz.qrc
+CONFIG += console
diff --git a/examples/statemachine/citizenquartz/citizenquartz.qrc b/examples/statemachine/citizenquartz/citizenquartz.qrc
new file mode 100644
index 0000000..bcc675a
--- /dev/null
+++ b/examples/statemachine/citizenquartz/citizenquartz.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>sound/alarm.wav</file>
+</qresource>
+</RCC> \ No newline at end of file
diff --git a/examples/statemachine/citizenquartz/clock.cpp b/examples/statemachine/citizenquartz/clock.cpp
new file mode 100644
index 0000000..51180f5
--- /dev/null
+++ b/examples/statemachine/citizenquartz/clock.cpp
@@ -0,0 +1,382 @@
+#include "clock.h"
+#include "clockbutton.h"
+#include "clockdisplay.h"
+#include "propertyaddstate.h"
+#include "timeperiod.h"
+
+#include <QStateMachine>
+#include <QState>
+#include <QHistoryState>
+
+#include <QPainter>
+#include <QTimer>
+#include <QSound>
+
+Clock::Clock(QGraphicsItem *parent)
+ : QGraphicsItem(parent),
+ m_stateMachine(0),
+ m_clockDisplay(0),
+ m_buttonA(0),
+ m_buttonB(0),
+ m_buttonC(0),
+ m_buttonD(0),
+ m_alarmState(0),
+ m_timeState(0),
+ m_updateState(0),
+ m_regularState(0),
+ m_alarmSound(new QSound(":/sound/alarm.wav", this))
+{
+}
+
+void Clock::initializeUi()
+{
+ QPainterPath path = shape();
+ QPointF pap;
+ qreal aap;
+
+ m_buttonA = new ClockButton("Button A", this);
+ pap = path.pointAtPercent(0.05);
+ aap = path.angleAtPercent(0.05);
+ m_buttonA->translate(pap.x(), pap.y());
+ m_buttonA->rotate(-aap);
+ connect(m_buttonA, SIGNAL(pressed()), this, SIGNAL(anyButtonPressed()));
+
+ m_buttonB = new ClockButton("Button B", this);
+ pap = path.pointAtPercent(0.77);
+ aap = path.angleAtPercent(0.77);
+ m_buttonB->translate(pap.x(), pap.y());
+ m_buttonB->rotate(-aap);
+ connect(m_buttonB, SIGNAL(pressed()), this, SIGNAL(anyButtonPressed()));
+
+ m_buttonC = new ClockButton("Button C", this);
+ pap = path.pointAtPercent(0.67);
+ aap = path.angleAtPercent(0.67);
+ m_buttonC->translate(pap.x(), pap.y());
+ m_buttonC->rotate(-aap);
+ connect(m_buttonC, SIGNAL(pressed()), this, SIGNAL(anyButtonPressed()));
+
+ m_buttonD = new ClockButton("Button D", this);
+ pap = path.pointAtPercent(0.57);
+ aap = path.angleAtPercent(0.57);
+ m_buttonD->translate(pap.x(), pap.y());
+ m_buttonD->rotate(-aap);
+ connect(m_buttonD, SIGNAL(pressed()), this, SIGNAL(anyButtonPressed()));
+
+ QGraphicsSimpleTextItem *label = new QGraphicsSimpleTextItem(this);
+ label->setText("CITIZEN");
+ label->setPos(0.0 - label->boundingRect().width() / 2.0, -100.0);
+
+ m_clockDisplay = new ClockDisplay(this);
+ m_clockDisplay->setCurrentTime(QDateTime::currentDateTime());
+
+ QTimer *timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(updateTime()));
+ timer->setInterval(1);
+ timer->start();
+ m_time.start();
+}
+
+void Clock::initializeStateMachine()
+{
+ m_stateMachine = new QStateMachine;
+
+ QState *displays = new QState(m_stateMachine->rootState());
+ displays->setObjectName("displays");
+ initializeDisplaysState(displays);
+
+ /*QState *alarmsBeep = new QState(m_stateMachine->rootState());
+ alarmsBeep->setObjectName("alarmsBeep");
+ initializeAlarmsBeepState(alarmsBeep);*/
+
+ m_stateMachine->setInitialState(displays);
+ m_stateMachine->start();
+}
+
+void Clock::initializeUpdateState(QState *updateState)
+{
+ QState *sec = new QState(updateState);
+ sec->setObjectName("sec");
+ sec->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditSecondMode);
+ updateState->setInitialState(sec);
+
+ PropertyAddState *secIncrease = new PropertyAddState(updateState);
+ secIncrease->setObjectName("sec ++");
+ secIncrease->addToProperty(m_clockDisplay, "currentTime",
+ TimePeriod().setSeconds(1));
+ sec->addTransition(m_buttonD, SIGNAL(pressed()), secIncrease);
+ secIncrease->addTransition(sec);
+
+ QState *oneMin = new QState(updateState);
+ oneMin->setObjectName("1 min");
+ oneMin->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditMinuteMode);
+ sec->addTransition(m_buttonC, SIGNAL(pressed()), oneMin);
+
+ PropertyAddState *oneMinIncrease = new PropertyAddState(updateState);
+ oneMinIncrease->setObjectName("1 min ++");
+ oneMinIncrease->addToProperty(m_clockDisplay, "currentTime",
+ TimePeriod().setMinutes(1));
+ oneMin->addTransition(m_buttonD, SIGNAL(pressed()), oneMinIncrease);
+ oneMinIncrease->addTransition(oneMin);
+
+ QState *tenMin = new QState(updateState);
+ tenMin->setObjectName("10 min");
+ tenMin->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditMinuteMode);
+ oneMin->addTransition(m_buttonC, SIGNAL(pressed()), tenMin);
+
+ PropertyAddState *tenMinIncrease = new PropertyAddState(updateState);
+ tenMinIncrease->setObjectName("10 min ++");
+ tenMinIncrease->addToProperty(m_clockDisplay, "currentTime",
+ TimePeriod().setMinutes(10));
+ tenMin->addTransition(m_buttonD, SIGNAL(pressed()), tenMinIncrease);
+ tenMinIncrease->addTransition(tenMin);
+
+ QState *hr = new QState(updateState);
+ hr->setObjectName("hr");
+ hr->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditHourMode);
+ tenMin->addTransition(m_buttonC, SIGNAL(pressed()), hr);
+
+ PropertyAddState *hrIncrease = new PropertyAddState(updateState);
+ hrIncrease->setObjectName("hr ++");
+ hrIncrease->addToProperty(m_clockDisplay, "currentTime",
+ TimePeriod().setHours(1));
+ hr->addTransition(m_buttonD, SIGNAL(pressed()), hrIncrease);
+ hrIncrease->addTransition(hr);
+
+ QState *mon = new QState(updateState);
+ mon->setObjectName("mon");
+ mon->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditMonthMode);
+ hr->addTransition(m_buttonC, SIGNAL(pressed()), mon);
+
+ PropertyAddState *monIncrease = new PropertyAddState(updateState);
+ monIncrease->setObjectName("mon ++");
+ monIncrease->addToProperty(m_clockDisplay, "currentTime",
+ TimePeriod().setMonths(1));
+ mon->addTransition(m_buttonD, SIGNAL(pressed()), monIncrease);
+ monIncrease->addTransition(mon);
+
+ QState *day = new QState(updateState);
+ day->setObjectName("day");
+ day->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditDayMode);
+ mon->addTransition(m_buttonC, SIGNAL(pressed()), day);
+
+ PropertyAddState *dayIncrease = new PropertyAddState(updateState);
+ dayIncrease->setObjectName("day ++");
+ dayIncrease->addToProperty(m_clockDisplay, "currentTime",
+ TimePeriod().setDays(1));
+ day->addTransition(m_buttonD, SIGNAL(pressed()), dayIncrease);
+ dayIncrease->addTransition(day);
+
+ QState *year = new QState(updateState);
+ year->setObjectName("year");
+ year->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditYearMode);
+ day->addTransition(m_buttonC, SIGNAL(pressed()), year);
+
+ PropertyAddState *yearIncrease = new PropertyAddState(updateState);
+ yearIncrease->setObjectName("year ++");
+ yearIncrease->addToProperty(m_clockDisplay, "currentTime",
+ TimePeriod().setYears(1));
+ year->addTransition(m_buttonD, SIGNAL(pressed()), yearIncrease);
+ yearIncrease->addTransition(year);
+ year->addTransition(m_buttonC, SIGNAL(pressed()), m_timeState);
+}
+
+void Clock::initializeRegularState(QState *regular)
+{
+ m_timeState = new QState(regular);
+ m_timeState->setObjectName("time");
+ m_timeState->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::CurrentTimeMode);
+
+ QState *date = new QState(regular);
+ date->setObjectName("date");
+ date->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::CurrentDateMode);
+
+ QState *dateTimerState = new QState(date);
+ dateTimerState->setObjectName("dateTimerState");
+
+ // Date state exits after 2 m
+ QTimer *dateTimer = new QTimer(dateTimerState);
+ dateTimer->setSingleShot(true);
+ dateTimer->setInterval(2*60000);
+ dateTimerState->invokeMethodOnEntry(dateTimer, "start");
+ dateTimerState->invokeMethodOnExit(dateTimer, "stop");
+
+ date->setInitialState(dateTimerState);
+
+ m_updateState = new QState(regular);
+ m_updateState->setObjectName("update");
+
+ // Update state exits after 2 m
+ QTimer *updateTimer = new QTimer(m_updateState);
+ updateTimer->setSingleShot(true);
+ updateTimer->setInterval(2 * 60000);
+ m_updateState->invokeMethodOnEntry(updateTimer, "start");
+ m_updateState->invokeMethodOnExit(updateTimer, "stop");
+
+ initializeUpdateState(m_updateState);
+
+ m_timeState->addTransition(m_buttonD, SIGNAL(pressed()), date);
+ date->addTransition(m_buttonD, SIGNAL(pressed()), m_timeState);
+ date->addTransition(dateTimer, SIGNAL(timeout()), m_timeState);
+
+ m_updateState->addTransition(updateTimer, SIGNAL(timeout()), m_timeState);
+ m_updateState->addTransition(m_buttonB, SIGNAL(pressed()), m_timeState);
+
+ regular->setInitialState(m_timeState);
+}
+
+void Clock::initializeAlarmUpdateState(QState *update)
+{
+ QState *hr = new QState(update);
+ hr->setObjectName("hr");
+ hr->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditAlarmHourMode);
+
+ PropertyAddState *hrInc = new PropertyAddState(update);
+ hrInc->setObjectName("hr ++");
+ hrInc->addToProperty(m_clockDisplay, "alarm", TimePeriod().setHours(1));
+ hr->addTransition(m_buttonD, SIGNAL(pressed()), hrInc);
+ hrInc->addTransition(hr);
+
+ QState *tenMin = new QState(update);
+ tenMin->setObjectName("10 min");
+ tenMin->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditAlarmTenMinuteMode);
+ hr->addTransition(m_buttonC, SIGNAL(pressed()), tenMin);
+
+ PropertyAddState *tenMinInc = new PropertyAddState(update);
+ tenMinInc->setObjectName("10 min ++");
+ tenMinInc->addToProperty(m_clockDisplay, "alarm", TimePeriod().setMinutes(10));
+ tenMin->addTransition(m_buttonD, SIGNAL(pressed()), tenMinInc);
+ tenMinInc->addTransition(tenMin);
+
+ QState *oneMin = new QState(update);
+ oneMin->setObjectName("1 min");
+ oneMin->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::EditAlarmMinuteMode);
+ tenMin->addTransition(m_buttonC, SIGNAL(pressed()), oneMin);
+
+ PropertyAddState *oneMinInc = new PropertyAddState(update);
+ oneMinInc->setObjectName("1 min ++");
+ oneMinInc->addToProperty(m_clockDisplay, "alarm", TimePeriod().setMinutes(1));
+ oneMin->addTransition(m_buttonD, SIGNAL(pressed()), oneMinInc);
+ oneMinInc->addTransition(oneMin);
+
+ oneMin->addTransition(m_buttonC, SIGNAL(pressed()), m_alarmState);
+ m_alarmState->addTransition(m_buttonC, SIGNAL(pressed()), hr);
+}
+
+void Clock::initializeOutState(QState *out)
+{
+ m_alarmState = new QState(out);
+ m_alarmState->setObjectName("alarmState");
+ m_alarmState->setPropertyOnEntry(m_clockDisplay, "displayMode", ClockDisplay::AlarmMode);
+ initializeAlarmState(m_alarmState);
+ out->setInitialState(m_alarmState);
+
+ QState *alarmUpdate = new QState(out);
+ alarmUpdate->setObjectName("alarmUpdate");
+ initializeAlarmUpdateState(alarmUpdate);
+
+ alarmUpdate->addTransition(m_buttonB, SIGNAL(pressed()), m_alarmState);
+ m_alarmState->addTransition(m_buttonA, SIGNAL(pressed()), m_regularState);
+}
+
+void Clock::initializeDisplaysState(QState *displays)
+{
+ m_regularState = new QState(displays);
+ m_regularState->setObjectName("regular");
+ initializeRegularState(m_regularState);
+ displays->setInitialState(m_regularState);
+
+ QState *out = new QState(displays);
+ out->setObjectName("out");
+
+ QTimer *outTimer = new QTimer(out);
+ outTimer->setSingleShot(true);
+ outTimer->setInterval(2 * 60000);
+ out->invokeMethodOnEntry(outTimer, "start");
+ out->invokeMethodOnExit(outTimer, "stop");
+
+ initializeOutState(out);
+
+ QState *wait = new QState(displays);
+ wait->setObjectName("wait");
+
+ QTimer *waitTimer = new QTimer(wait);
+ waitTimer->setSingleShot(true);
+ waitTimer->setInterval(2000);
+ wait->invokeMethodOnEntry(waitTimer, "start");
+ wait->invokeMethodOnExit(waitTimer, "stop");
+
+ m_timeState->addTransition(m_buttonC, SIGNAL(pressed()), wait);
+ wait->addTransition(waitTimer, SIGNAL(timeout()), m_updateState);
+ wait->addTransition(m_buttonC, SIGNAL(released()), m_timeState);
+ m_timeState->addTransition(m_buttonA, SIGNAL(pressed()), m_alarmState);
+ out->addTransition(outTimer, SIGNAL(timeout()), m_regularState);
+}
+
+void Clock::initializeAlarmState(QState *alarmState)
+{
+ QState *offState = new QState(alarmState);
+ offState->setObjectName("alarmOff");
+ offState->setPropertyOnEntry(m_clockDisplay, "alarmEnabled", false);
+
+ QState *onState = new QState(alarmState);
+ onState->setObjectName("alarmOn");
+ onState->setPropertyOnEntry(m_clockDisplay, "alarmEnabled", true);
+
+ QHistoryState *history = alarmState->addHistoryState();
+ history->setObjectName("alarmHistory");
+ history->setDefaultState(onState);
+
+ offState->addTransition(m_buttonD, SIGNAL(pressed()), onState);
+ onState->addTransition(m_buttonD, SIGNAL(pressed()), offState);
+
+ QState *intermediate = new QState(alarmState);
+ intermediate->addTransition(history);
+
+ alarmState->setInitialState(intermediate);
+}
+
+QRectF Clock::boundingRect() const
+{
+ return shape().boundingRect();
+}
+
+QPainterPath Clock::shape() const
+{
+ QPainterPath path;
+ path.addRoundedRect(QRectF(-140.0, -100.0, 280.0, 200.0), 50.0, 50.0, Qt::RelativeSize);
+
+ return path;
+}
+
+void Clock::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ painter->setPen(Qt::black);
+ painter->setBrush(Qt::NoBrush);
+
+ // Clock face
+ painter->drawPath(shape());
+}
+
+void Clock::updateTime()
+{
+ int elapsed = m_time.elapsed();
+ if (elapsed > 0) {
+ m_time.restart();
+ QDateTime currentTime = m_clockDisplay->currentTime();
+ m_clockDisplay->setCurrentTime(currentTime.addMSecs(elapsed));
+
+ update();
+ }
+}
+
+void Clock::playSound()
+{
+ m_alarmSound->stop();
+ m_alarmSound->play();
+}
+
+void Clock::stopSound()
+{
+ m_alarmSound->stop();
+}
+
diff --git a/examples/statemachine/citizenquartz/clock.h b/examples/statemachine/citizenquartz/clock.h
new file mode 100644
index 0000000..aee1b55
--- /dev/null
+++ b/examples/statemachine/citizenquartz/clock.h
@@ -0,0 +1,60 @@
+#ifndef CLOCK_H
+#define CLOCK_H
+
+#include <QGraphicsItem>
+#include <QTime>
+
+class ClockButton ;
+class ClockDisplay ;
+class QStateMachine ;
+class QState ;
+class QTimerState ;
+class QSound ;
+
+class Clock: public QObject, public QGraphicsItem
+{
+ Q_OBJECT
+public:
+ Clock(QGraphicsItem *parent = 0);
+
+ void initializeUi();
+ void initializeStateMachine();
+
+ virtual QRectF boundingRect() const;
+ virtual QPainterPath shape() const;
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+signals:
+ void alarm();
+ void anyButtonPressed();
+
+public slots:
+ void updateTime();
+ void playSound();
+ void stopSound();
+
+private:
+ void initializeDisplaysState(QState *displays);
+ void initializeAlarmState(QState *alarmState);
+ void initializeRegularState(QState *regular);
+ void initializeUpdateState(QState *update);
+ void initializeOutState(QState *out);
+ void initializeAlarmUpdateState(QState *update);
+
+ QStateMachine *m_stateMachine;
+ ClockDisplay *m_clockDisplay;
+ ClockButton *m_buttonA;
+ ClockButton *m_buttonB;
+ ClockButton *m_buttonC;
+ ClockButton *m_buttonD;
+
+ QState *m_alarmState;
+ QState *m_timeState;
+ QState *m_updateState;
+ QState *m_regularState;
+
+ QSound *m_alarmSound;
+ QTime m_time;
+};
+
+#endif // CLOCK_H
diff --git a/examples/statemachine/citizenquartz/clockbutton.cpp b/examples/statemachine/citizenquartz/clockbutton.cpp
new file mode 100644
index 0000000..7b86891
--- /dev/null
+++ b/examples/statemachine/citizenquartz/clockbutton.cpp
@@ -0,0 +1,39 @@
+#include "clockbutton.h"
+
+#include <QPainter>
+
+ClockButton::ClockButton(const QString &name, QGraphicsItem *parent) : QGraphicsItem(parent)
+{
+ setObjectName(name);
+ setToolTip(name);
+ setAcceptedMouseButtons(Qt::LeftButton);
+}
+
+QRectF ClockButton::boundingRect() const
+{
+ return QRectF(-10.0, -10.0, 20.0, 20.0);
+}
+
+QPainterPath ClockButton::shape() const
+{
+ QPainterPath path;
+ path.addRoundedRect(boundingRect(), 15.0, 15.0, Qt::RelativeSize);
+
+ return path;
+}
+
+void ClockButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ painter->setBrush(Qt::black);
+ painter->drawPath(shape());
+}
+
+void ClockButton::mousePressEvent(QGraphicsSceneMouseEvent *)
+{
+ emit pressed();
+}
+
+void ClockButton::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ emit released();
+} \ No newline at end of file
diff --git a/examples/statemachine/citizenquartz/clockbutton.h b/examples/statemachine/citizenquartz/clockbutton.h
new file mode 100644
index 0000000..02a7ccd
--- /dev/null
+++ b/examples/statemachine/citizenquartz/clockbutton.h
@@ -0,0 +1,25 @@
+#ifndef CLOCKBUTTON_H
+#define CLOCKBUTTON_H
+
+#include <QGraphicsItem>
+
+class ClockButton: public QObject, public QGraphicsItem
+{
+ Q_OBJECT
+public:
+ ClockButton(const QString &name, QGraphicsItem *parent = 0);
+
+ virtual QRectF boundingRect() const;
+ virtual QPainterPath shape() const;
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *);
+
+protected:
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+signals:
+ void pressed();
+ void released();
+};
+
+#endif //CLOCKBUTTON_H
diff --git a/examples/statemachine/citizenquartz/clockdisplay.cpp b/examples/statemachine/citizenquartz/clockdisplay.cpp
new file mode 100644
index 0000000..717b881
--- /dev/null
+++ b/examples/statemachine/citizenquartz/clockdisplay.cpp
@@ -0,0 +1,140 @@
+#include "clockdisplay.h"
+
+#include <QPainter>
+#include <QTimer>
+
+ClockDisplay::ClockDisplay(QGraphicsItem *parent)
+ : QGraphicsItem(parent),
+ m_displayMode(CurrentTimeMode),
+ m_currentTime(QDate(1970, 1, 1), QTime(0, 0)),
+ m_alarm(0, 0),
+ m_alarmEnabled(false),
+ m_blink(false)
+
+{
+ m_text = new QGraphicsTextItem(this);
+
+ QTimer *timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(toggleBlinkFlag()));
+ timer->start(500);
+
+ QFont font = m_text->font();
+ font.setPointSizeF(20.0);
+ m_text->setFont(font);
+
+ m_text->translate(-100.0, -20.0);
+
+ QPixmap pm(":/images/alarm.png");
+ m_alarmSymbol = new QGraphicsPixmapItem(pm, this);
+ m_alarmSymbol->translate(-100.0, -60.0);
+ m_alarmSymbol->setOffset(5.0, 5.0);
+ m_alarmSymbol->scale(0.5, 0.5);
+}
+
+ClockDisplay::~ClockDisplay()
+{
+}
+
+void ClockDisplay::toggleBlinkFlag()
+{
+ m_blink = !m_blink;
+ update();
+}
+
+void ClockDisplay::updateText()
+{
+ switch (m_displayMode) {
+ case EditSecondMode:
+ if (m_blink) {
+ m_text->setHtml(m_currentTime.toString("hh:mm:'<font color=\"transparent\">'ss'</font>'"));
+ break;
+ }
+ // fall throoough
+ case EditMinuteMode:
+ if (m_blink) {
+ m_text->setHtml(m_currentTime.toString("hh:'<font color=\"transparent\">'mm'</font>':ss"));
+ break;
+ }
+
+ // fall throoough
+ case EditHourMode:
+ if (m_blink) {
+ m_text->setHtml(m_currentTime.toString("'<font color=\"transparent\">'hh'</font>':mm:ss"));
+ break;
+ }
+
+ // fall throoough
+ case CurrentTimeMode:
+ m_text->setHtml(m_currentTime.toString("hh:mm:ss"));
+ break;
+
+ case EditMonthMode:
+ if (m_blink) {
+ m_text->setHtml(m_currentTime.toString("yyyy.'<font color=\"transparent\">'MM'</font>'.dd"));
+ break;
+ }
+
+ // fall throoough
+ case EditDayMode:
+ if (m_blink) {
+ m_text->setHtml(m_currentTime.toString("yyyy.MM.'<font color=\"transparent\">'dd'</font>'"));
+ break;
+ }
+
+ // fall throoough
+ case EditYearMode:
+ if (m_blink) {
+ m_text->setHtml(m_currentTime.toString("'<font color=\"transparent\">'yyyy'</font>'.MM.dd"));
+ break;
+ }
+
+ // fall throoough
+ case CurrentDateMode:
+ m_text->setHtml(m_currentTime.toString("yyyy.MM.dd"));
+ break;
+
+ case EditAlarmHourMode:
+ if (m_blink) {
+ m_text->setHtml(m_alarm.toString("'<font color=\"transparent\">'hh'</font>':mm"));
+ break;
+ }
+
+ // fall throooough
+ case EditAlarmTenMinuteMode:
+ case EditAlarmMinuteMode:
+ if (m_blink) {
+ m_text->setHtml(m_alarm.toString("hh:'<font color=\"transparent\">'mm'</font>'"));
+ break;
+ }
+
+ // fall throoough
+ case AlarmMode:
+ m_text->setHtml(m_alarm.toString("hh:mm"));
+ break;
+
+ default:
+ m_text->setHtml("Not implemented");
+ };
+}
+
+QRectF ClockDisplay::boundingRect() const
+{
+ return QRectF(-100.0, -60.0, 200.0, 120.0);
+}
+
+void ClockDisplay::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ if (m_alarmEnabled)
+ m_alarmSymbol->setVisible(true);
+
+ updateText();
+
+ // Screen
+ painter->drawRoundedRect(boundingRect(), 15.0, 15.0, Qt::RelativeSize);
+
+ // Button grid
+ painter->drawLine(QPointF(-100.0, -20.0), QPointF(100.0, -20.0));
+ painter->drawLine(QPointF(-50.0, -60.0), QPointF(-50.0, -20.0));
+ painter->drawLine(QPointF(0.0, -60.0), QPointF(0.0, -20.0));
+ painter->drawLine(QPointF(50.0, -60.0), QPointF(50.0, -20.0));
+}
diff --git a/examples/statemachine/citizenquartz/clockdisplay.h b/examples/statemachine/citizenquartz/clockdisplay.h
new file mode 100644
index 0000000..e0ac8bb
--- /dev/null
+++ b/examples/statemachine/citizenquartz/clockdisplay.h
@@ -0,0 +1,75 @@
+#ifndef CLOCKDISPLAY_H
+#define CLOCKDISPLAY_H
+
+#include <QObject>
+#include <QGraphicsItem>
+#include <QDateTime>
+
+class ClockDisplay: public QObject, public QGraphicsItem
+{
+ Q_OBJECT
+ Q_ENUMS(DisplayMode)
+ Q_PROPERTY(DisplayMode displayMode READ displayMode WRITE setDisplayMode)
+ Q_PROPERTY(QDateTime currentTime READ currentTime WRITE setCurrentTime)
+ Q_PROPERTY(QTime alarm READ alarm WRITE setAlarm)
+ Q_PROPERTY(bool alarmEnabled READ alarmEnabled WRITE setAlarmEnabled)
+public:
+ enum DisplayMode {
+ CurrentTimeMode,
+ EditSecondMode,
+ EditMinuteMode,
+ EditHourMode,
+
+ CurrentDateMode,
+ EditMonthMode,
+ EditDayMode,
+ EditYearMode,
+
+ AlarmMode,
+ EditAlarmHourMode,
+ EditAlarmTenMinuteMode,
+ EditAlarmMinuteMode,
+
+ ChimeMode,
+ StopWatchMode,
+ ModeCount
+ };
+
+ ClockDisplay(QGraphicsItem *parent = 0);
+ virtual ~ClockDisplay();
+
+ void setDisplayMode(DisplayMode displayMode) { m_displayMode = displayMode; update(); }
+ DisplayMode displayMode() const { return m_displayMode; }
+
+ QDateTime currentTime() const { return m_currentTime; }
+ void setCurrentTime(const QDateTime &time) { m_currentTime = time; update(); }
+
+ QTime alarm() const { return m_alarm; }
+ void setAlarm(const QTime &time) { m_alarm = time; update(); }
+
+ bool alarmEnabled() const { return m_alarmEnabled; }
+ void setAlarmEnabled(bool enabled) { m_alarmEnabled = enabled; update(); }
+
+ virtual QRectF boundingRect() const;
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *);
+
+private slots:
+ void toggleBlinkFlag();
+
+private:
+ void updateText();
+
+ DisplayMode m_displayMode;
+
+ QDateTime m_currentTime;
+ QTime m_alarm;
+
+ QGraphicsTextItem *m_text;
+ QGraphicsPixmapItem *m_alarmSymbol;
+
+ uint m_alarmEnabled : 1;
+ uint m_blink : 1;
+ uint m_reserved : 30;
+};
+
+#endif
diff --git a/examples/statemachine/citizenquartz/images/alarm.png b/examples/statemachine/citizenquartz/images/alarm.png
new file mode 100644
index 0000000..a19778d
--- /dev/null
+++ b/examples/statemachine/citizenquartz/images/alarm.png
Binary files differ
diff --git a/examples/statemachine/citizenquartz/main.cpp b/examples/statemachine/citizenquartz/main.cpp
new file mode 100644
index 0000000..2c6b14c
--- /dev/null
+++ b/examples/statemachine/citizenquartz/main.cpp
@@ -0,0 +1,23 @@
+#include <QApplication>
+#include <QGraphicsScene>
+#include <QGraphicsView>
+
+#include "clock.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QGraphicsScene scene;
+
+ Clock *clock = new Clock;
+ clock->initializeUi();
+ clock->initializeStateMachine();
+ scene.addItem(clock);
+
+ QGraphicsView view(&scene);
+ view.setRenderHint(QPainter::Antialiasing);
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/statemachine/citizenquartz/propertyaddstate.cpp b/examples/statemachine/citizenquartz/propertyaddstate.cpp
new file mode 100644
index 0000000..f129c8d
--- /dev/null
+++ b/examples/statemachine/citizenquartz/propertyaddstate.cpp
@@ -0,0 +1,46 @@
+#include "PropertyAddState.h"
+#include "timeperiod.h"
+
+#include <QDateTime>
+#include <QDebug>
+
+PropertyAddState::PropertyAddState(QState *parent)
+ : QState(parent)
+{
+}
+
+void PropertyAddState::addToProperty(QObject *object, const char *propertyName,
+ const QVariant &valueToAdd)
+{
+ m_propertyAdditions.append(PropertyAdder(object, propertyName, valueToAdd));
+}
+
+QVariant PropertyAddState::addProperties(const QVariant &current, const QVariant &toAdd) const
+{
+ QVariant result;
+ switch (current.type()) {
+ case QVariant::DateTime:
+ result = current.toDateTime() + qvariant_cast<TimePeriod>(toAdd);
+ break;
+ case QVariant::Time:
+ result = current.toTime() + qvariant_cast<TimePeriod>(toAdd);
+ break;
+ default:
+ qWarning("PropertyAddState::addProperties: QVariant type '%s' not supported",
+ current.typeName());
+ };
+
+ return result;
+}
+
+void PropertyAddState::onEntry()
+{
+ foreach (PropertyAdder propertyAdder, m_propertyAdditions) {
+ QObject *object = propertyAdder.object;
+ const char *propertyName = propertyAdder.propertyName;
+ QVariant toAdd = propertyAdder.valueToAdd;
+ QVariant current = object->property(propertyName);
+
+ object->setProperty(propertyName, addProperties(current, toAdd));
+ }
+}
diff --git a/examples/statemachine/citizenquartz/propertyaddstate.h b/examples/statemachine/citizenquartz/propertyaddstate.h
new file mode 100644
index 0000000..96f45fc
--- /dev/null
+++ b/examples/statemachine/citizenquartz/propertyaddstate.h
@@ -0,0 +1,33 @@
+#ifndef PropertyAddState_H
+#define PropertyAddState_H
+
+#include <qstate.h>
+
+#include <QVariant>
+#include <QList>
+
+class PropertyAddState: public QState
+{
+public:
+ PropertyAddState(QState *parent = 0);
+
+ void addToProperty(QObject *object, const char *propertyName, const QVariant &valueToAdd);
+ virtual void onEntry();
+
+private:
+ QVariant addProperties(const QVariant &current, const QVariant &toAdd) const;
+
+ struct PropertyAdder {
+ PropertyAdder(QObject *_object, const char *_propertyName, const QVariant &_valueToAdd)
+ : object(_object), propertyName(_propertyName), valueToAdd(_valueToAdd)
+ {
+ }
+
+ QObject *object;
+ const char *propertyName;
+ QVariant valueToAdd;
+ };
+ QList<PropertyAdder> m_propertyAdditions;
+};
+
+#endif // PropertyAddState_H
diff --git a/examples/statemachine/citizenquartz/sound/alarm.wav b/examples/statemachine/citizenquartz/sound/alarm.wav
new file mode 100644
index 0000000..1d9486f
--- /dev/null
+++ b/examples/statemachine/citizenquartz/sound/alarm.wav
Binary files differ
diff --git a/examples/statemachine/citizenquartz/timeperiod.h b/examples/statemachine/citizenquartz/timeperiod.h
new file mode 100644
index 0000000..a64c17c
--- /dev/null
+++ b/examples/statemachine/citizenquartz/timeperiod.h
@@ -0,0 +1,84 @@
+#ifndef TIMEPERIOD_H
+#define TIMEPERIOD_H
+
+#include <QDateTime>
+#include <QTime>
+#include <QDebug>
+
+class TimePeriod
+{
+public:
+ TimePeriod() : m_seconds(0), m_minutes(0), m_hours(0), m_days(0), m_months(0), m_years(0)
+ {
+ }
+
+ TimePeriod &setSeconds(int seconds) { m_seconds = seconds; return *this; }
+ int seconds() const { return m_seconds; }
+
+ TimePeriod &setMinutes(int minutes) { m_minutes = minutes; return *this; }
+ int minutes() const { return m_minutes; }
+
+ TimePeriod &setHours(int hours) { m_hours = hours; return *this; }
+ int hours() const { return m_hours; }
+
+ TimePeriod &setDays(int days) { m_days = days; return *this; }
+ int days() const { return m_days; }
+
+ TimePeriod &setMonths(int months) { m_months = months; return *this; }
+ int months() const { return m_months; }
+
+ TimePeriod &setYears(int years) { m_years = years; return *this; }
+ int years() const { return m_years; }
+
+ operator QVariant() const
+ {
+ QVariant v;
+ qVariantSetValue<TimePeriod>(v, *this);
+ return v;
+ }
+
+private:
+ int m_seconds;
+ int m_minutes;
+ int m_hours;
+ int m_days;
+ int m_months;
+ int m_years;
+};
+
+inline void operator+=(QDateTime &dateTime, const TimePeriod &timePeriod)
+{
+ dateTime = dateTime.addSecs(timePeriod.seconds());
+ dateTime = dateTime.addSecs(timePeriod.minutes() * 60);
+ dateTime = dateTime.addSecs(timePeriod.hours() * 3600);
+ dateTime = dateTime.addDays(timePeriod.days());
+ dateTime = dateTime.addMonths(timePeriod.months());
+ dateTime = dateTime.addYears(timePeriod.years());
+}
+
+inline QDateTime operator+(const QDateTime &dateTime, const TimePeriod &timePeriod)
+{
+ QDateTime result(dateTime);
+ result += timePeriod;
+
+ return result;
+}
+
+inline void operator+=(QTime &time, const TimePeriod &timePeriod)
+{
+ time = time.addSecs(timePeriod.seconds());
+ time = time.addSecs(timePeriod.minutes() * 60);
+ time = time.addSecs(timePeriod.hours() * 3600);
+}
+
+inline QTime operator+(const QTime &time, const TimePeriod &timePeriod)
+{
+ QTime result(time);
+ result += timePeriod;
+
+ return time;
+}
+
+Q_DECLARE_METATYPE(TimePeriod)
+
+#endif \\ TIMEPERIOD_H
diff --git a/examples/statemachine/clockticking/clockticking.pro b/examples/statemachine/clockticking/clockticking.pro
new file mode 100644
index 0000000..bff9cb8
--- /dev/null
+++ b/examples/statemachine/clockticking/clockticking.pro
@@ -0,0 +1,10 @@
+QT = core
+TEMPLATE = app
+TARGET =
+win32: CONFIG += console
+mac:CONFIG -= app_bundle
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
diff --git a/examples/statemachine/clockticking/main.cpp b/examples/statemachine/clockticking/main.cpp
new file mode 100644
index 0000000..e903988
--- /dev/null
+++ b/examples/statemachine/clockticking/main.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <stdio.h>
+#ifdef QT_STATEMACHINE_SOLUTION
+#include <qstatemachine.h>
+#include <qstate.h>
+#include <qtransition.h>
+#endif
+
+class ClockEvent : public QEvent
+{
+public:
+ ClockEvent() : QEvent(QEvent::Type(QEvent::User+2))
+ {}
+};
+
+class ClockState : public QState
+{
+public:
+ ClockState(QStateMachine *machine, QState *parent)
+ : QState(parent), m_machine(machine) {}
+
+protected:
+ virtual void onEntry()
+ {
+ fprintf(stdout, "ClockState entered; posting the initial tick\n");
+ m_machine->postEvent(new ClockEvent());
+ }
+
+private:
+ QStateMachine *m_machine;
+};
+
+class ClockTransition : public QAbstractTransition
+{
+public:
+ ClockTransition(QStateMachine *machine)
+ : QAbstractTransition(), m_machine(machine) { }
+
+protected:
+ virtual bool eventTest(QEvent *e) const {
+ return (e->type() == QEvent::User+2);
+ }
+ virtual void onTransition()
+ {
+ fprintf(stdout, "ClockTransition triggered; posting another tick with a delay of 1 second\n");
+ m_machine->postEvent(new ClockEvent(), 1000);
+ }
+
+private:
+ QStateMachine *m_machine;
+};
+
+class ClockListener : public QAbstractTransition
+{
+public:
+ ClockListener()
+ : QAbstractTransition() {}
+
+protected:
+ virtual bool eventTest(QEvent *e) const {
+ return (e->type() == QEvent::User+2);
+ }
+ virtual void onTransition()
+ {
+ fprintf(stdout, "ClockListener heard a tick!\n");
+ }
+};
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QStateMachine machine;
+ QState *group = new QState(QState::ParallelGroup);
+ group->setObjectName("group");
+
+ ClockState *clock = new ClockState(&machine, group);
+ clock->setObjectName("clock");
+ clock->addTransition(new ClockTransition(&machine));
+
+ QState *listener = new QState(group);
+ listener->setObjectName("listener");
+ listener->addTransition(new ClockListener());
+
+ machine.addState(group);
+ machine.setInitialState(group);
+ machine.start();
+
+ return app.exec();
+}
diff --git a/examples/statemachine/composition/composition.pro b/examples/statemachine/composition/composition.pro
new file mode 100644
index 0000000..6a976cb
--- /dev/null
+++ b/examples/statemachine/composition/composition.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
diff --git a/examples/statemachine/composition/main.cpp b/examples/statemachine/composition/main.cpp
new file mode 100644
index 0000000..892542d
--- /dev/null
+++ b/examples/statemachine/composition/main.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#ifdef QT_STATEMACHINE_SOLUTION
+#include <qstatemachine.h>
+#include <qstate.h>
+#include <qfinalstate.h>
+#endif
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ QLabel label;
+ label.setAlignment(Qt::AlignCenter);
+
+ QStateMachine machine;
+
+ QState *s1 = new QState();
+ s1->setObjectName("s1");
+ s1->setPropertyOnEntry(&label, "text", "In S1, hang on...");
+ s1->setPropertyOnEntry(&label, "geometry", QRect(100, 100, 200, 100));
+
+ QState *s1_timer = new QState(s1);
+ s1_timer->setObjectName("s1_timer");
+ QTimer t1;
+ t1.setInterval(2000);
+ s1_timer->invokeMethodOnEntry(&t1, "start");
+ QFinalState *s1_done = new QFinalState(s1);
+ s1_done->setObjectName("s1_done");
+ s1_timer->addTransition(&t1, SIGNAL(timeout()), s1_done);
+ s1->setInitialState(s1_timer);
+
+ QState *s2 = new QState();
+ s2->setObjectName("s2");
+ s2->setPropertyOnEntry(&label, "text", "In S2, I'm gonna quit on you...");
+ s2->setPropertyOnEntry(&label, "geometry", QRect(300, 300, 300, 100));
+// s2->invokeMethodOnEntry(&label, "setNum", QList<QVariant>() << 123);
+// s2->invokeMethodOnEntry(&label, "showMaximized");
+
+ QState *s2_timer = new QState(s2);
+ s2_timer->setObjectName("s2_timer");
+ QTimer t2;
+ t2.setInterval(2000);
+ s2_timer->invokeMethodOnEntry(&t2, "start");
+ QFinalState *s2_done = new QFinalState(s2);
+ s2_done->setObjectName("s2_done");
+ s2_timer->addTransition(&t2, SIGNAL(timeout()), s2_done);
+ s2->setInitialState(s2_timer);
+
+ s1->addFinishedTransition(s2);
+
+ QFinalState *s3 = new QFinalState();
+ s3->setObjectName("s3");
+ s2->addFinishedTransition(s3);
+
+ machine.addState(s1);
+ machine.addState(s2);
+ machine.addState(s3);
+ machine.setInitialState(s1);
+ QObject::connect(&machine, SIGNAL(finished()), &app, SLOT(quit()));
+ machine.start();
+
+ label.show();
+ return app.exec();
+}
diff --git a/examples/statemachine/eventtransitions/eventtransitions.pro b/examples/statemachine/eventtransitions/eventtransitions.pro
new file mode 100644
index 0000000..6a976cb
--- /dev/null
+++ b/examples/statemachine/eventtransitions/eventtransitions.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
diff --git a/examples/statemachine/eventtransitions/main.cpp b/examples/statemachine/eventtransitions/main.cpp
new file mode 100644
index 0000000..51b2d82
--- /dev/null
+++ b/examples/statemachine/eventtransitions/main.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#ifdef QT_STATEMACHINE_SOLUTION
+#include <qstatemachine.h>
+#include <qstate.h>
+#include <qeventtransition.h>
+#endif
+
+class Window : public QWidget
+{
+public:
+ Window(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ QPushButton *button = new QPushButton(this);
+ button->setGeometry(QRect(100, 100, 100, 100));
+
+ QStateMachine *machine = new QStateMachine(this);
+
+ QState *s1 = new QState();
+ s1->setPropertyOnEntry(button, "text", "Outside");
+
+ QState *s2 = new QState();
+ s2->setPropertyOnEntry(button, "text", "Inside");
+
+ QEventTransition *enterTransition = new QEventTransition(button, QEvent::Enter);
+ enterTransition->setTargetState(s2);
+ s1->addTransition(enterTransition);
+
+ QEventTransition *leaveTransition = new QEventTransition(button, QEvent::Leave);
+ leaveTransition->setTargetState(s1);
+ s2->addTransition(leaveTransition);
+
+ QState *s3 = new QState();
+ s3->setPropertyOnEntry(button, "text", "Pressing...");
+
+ QEventTransition *pressTransition = new QEventTransition(button, QEvent::MouseButtonPress);
+ pressTransition->setTargetState(s3);
+ s2->addTransition(pressTransition);
+
+ QEventTransition *releaseTransition = new QEventTransition(button, QEvent::MouseButtonRelease);
+ releaseTransition->setTargetState(s2);
+ s3->addTransition(releaseTransition);
+
+ machine->addState(s1);
+ machine->addState(s2);
+ machine->addState(s3);
+ machine->setInitialState(s1);
+ QObject::connect(machine, SIGNAL(finished()), qApp, SLOT(quit()));
+ machine->start();
+ }
+};
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ Window window;
+ window.resize(300, 300);
+ window.show();
+
+ return app.exec();
+}
diff --git a/examples/statemachine/factorial/factorial.pro b/examples/statemachine/factorial/factorial.pro
new file mode 100644
index 0000000..ac79117
--- /dev/null
+++ b/examples/statemachine/factorial/factorial.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+TARGET =
+QT = core
+win32: CONFIG += console
+mac:CONFIG -= app_bundle
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
diff --git a/examples/statemachine/factorial/main.cpp b/examples/statemachine/factorial/main.cpp
new file mode 100644
index 0000000..985b09f
--- /dev/null
+++ b/examples/statemachine/factorial/main.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <stdio.h>
+#ifdef QT_STATEMACHINE_SOLUTION
+#include <qstatemachine.h>
+#include <qstate.h>
+#include <qsignaltransition.h>
+#include <qfinalstate.h>
+#endif
+
+class Factorial : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int x READ x WRITE setX)
+ Q_PROPERTY(int fac READ fac WRITE setFac)
+public:
+ Factorial(QObject *parent = 0)
+ : QObject(parent)
+ {
+ m_fac = 1;
+ m_x = -1;
+ }
+
+ int x() const
+ {
+ return m_x;
+ }
+
+ void setX(int x)
+ {
+ if (x == m_x)
+ return;
+ m_x = x;
+ emit xChanged();
+ }
+
+ int fac() const
+ {
+ return m_fac;
+ }
+
+ void setFac(int fac)
+ {
+ m_fac = fac;
+ }
+
+Q_SIGNALS:
+ void xChanged();
+
+private:
+ int m_x;
+ int m_fac;
+};
+
+class FactorialLoopTransition : public QSignalTransition
+{
+public:
+ FactorialLoopTransition(Factorial *fact)
+ : QSignalTransition(fact, SIGNAL(xChanged())), m_fact(fact)
+ {}
+
+ virtual bool eventTest(QEvent *) const
+ {
+ return m_fact->property("x").toInt() > 1;
+ }
+
+ virtual void onTransition()
+ {
+ int x = m_fact->property("x").toInt();
+ int fac = m_fact->property("fac").toInt();
+ m_fact->setProperty("fac", x * fac);
+ m_fact->setProperty("x", x - 1);
+ }
+
+private:
+ Factorial *m_fact;
+};
+
+class FactorialDoneTransition : public QSignalTransition
+{
+public:
+ FactorialDoneTransition(Factorial *fact)
+ : QSignalTransition(fact, SIGNAL(xChanged())), m_fact(fact)
+ {}
+
+ virtual bool eventTest(QEvent *) const
+ {
+ return m_fact->property("x").toInt() <= 1;
+ }
+
+ virtual void onTransition()
+ {
+ fprintf(stdout, "%d\n", m_fact->property("fac").toInt());
+ }
+
+private:
+ Factorial *m_fact;
+};
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+
+ Factorial factorial;
+
+ QStateMachine machine;
+
+ QState *computing = new QState(machine.rootState());
+ computing->addTransition(new FactorialLoopTransition(&factorial));
+
+ QFinalState *done = new QFinalState(machine.rootState());
+ FactorialDoneTransition *doneTransition = new FactorialDoneTransition(&factorial);
+ doneTransition->setTargetState(done);
+ computing->addTransition(doneTransition);
+
+ QState *initialize = new QState(machine.rootState());
+ initialize->setPropertyOnEntry(&factorial, "x", 6);
+ FactorialLoopTransition *enterLoopTransition = new FactorialLoopTransition(&factorial);
+ enterLoopTransition->setTargetState(computing);
+ initialize->addTransition(enterLoopTransition);
+
+ QObject::connect(&machine, SIGNAL(finished()), &app, SLOT(quit()));
+
+ machine.setInitialState(initialize);
+ machine.start();
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/examples/statemachine/helloworld/helloworld.pro b/examples/statemachine/helloworld/helloworld.pro
new file mode 100644
index 0000000..ac79117
--- /dev/null
+++ b/examples/statemachine/helloworld/helloworld.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+TARGET =
+QT = core
+win32: CONFIG += console
+mac:CONFIG -= app_bundle
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
diff --git a/examples/statemachine/helloworld/main.cpp b/examples/statemachine/helloworld/main.cpp
new file mode 100644
index 0000000..a124623
--- /dev/null
+++ b/examples/statemachine/helloworld/main.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#ifdef QT_STATEMACHINE_SOLUTION
+#include <qstatemachine.h>
+#include <qstate.h>
+#include <qfinalstate.h>
+#endif
+
+class S0 : public QState
+{
+public:
+ S0(QState *parent = 0)
+ : QState(parent) {}
+
+ virtual void onEntry()
+ {
+ fprintf(stdout, "Hello world!\n");
+ }
+};
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QStateMachine machine;
+ QState *s0 = new S0();
+ QFinalState *s1 = new QFinalState();
+ s0->addTransition(s1);
+
+ machine.addState(s0);
+ machine.addState(s1);
+ machine.setInitialState(s0);
+
+ QObject::connect(&machine, SIGNAL(finished()), QCoreApplication::instance(), SLOT(quit()));
+ machine.start();
+
+ return app.exec();
+}
diff --git a/examples/statemachine/pauseandresume/main.cpp b/examples/statemachine/pauseandresume/main.cpp
new file mode 100644
index 0000000..7aed84b
--- /dev/null
+++ b/examples/statemachine/pauseandresume/main.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#ifdef QT_STATEMACHINE_SOLUTION
+#include <qstatemachine.h>
+#include <qstate.h>
+#include <qfinalstate.h>
+#include <qhistorystate.h>
+#endif
+
+class Window : public QWidget
+{
+public:
+ Window(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ QPushButton *pb = new QPushButton("Go");
+ QPushButton *pauseButton = new QPushButton("Pause");
+ QPushButton *quitButton = new QPushButton("Quit");
+ QVBoxLayout *vbox = new QVBoxLayout(this);
+ vbox->addWidget(pb);
+ vbox->addWidget(pauseButton);
+ vbox->addWidget(quitButton);
+
+ QStateMachine *machine = new QStateMachine(this);
+
+ QState *process = new QState(machine->rootState());
+ process->setObjectName("process");
+
+ QState *s1 = new QState(process);
+ s1->setObjectName("s1");
+ QState *s2 = new QState(process);
+ s2->setObjectName("s2");
+ s1->addTransition(pb, SIGNAL(clicked()), s2);
+ s2->addTransition(pb, SIGNAL(clicked()), s1);
+
+ QHistoryState *h = process->addHistoryState();
+ h->setDefaultState(s1);
+
+ QState *interrupted = new QState(machine->rootState());
+ interrupted->setObjectName("interrupted");
+ QFinalState *terminated = new QFinalState(machine->rootState());
+ terminated->setObjectName("terminated");
+ interrupted->addTransition(pauseButton, SIGNAL(clicked()), h);
+ interrupted->addTransition(quitButton, SIGNAL(clicked()), terminated);
+
+ process->addTransition(pauseButton, SIGNAL(clicked()), interrupted);
+ process->addTransition(quitButton, SIGNAL(clicked()), terminated);
+
+ process->setInitialState(s1);
+ machine->setInitialState(process);
+ QObject::connect(machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit()));
+ machine->start();
+ }
+};
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ Window win;
+ win.show();
+ return app.exec();
+}
diff --git a/examples/statemachine/pauseandresume/pauseandresume.pro b/examples/statemachine/pauseandresume/pauseandresume.pro
new file mode 100644
index 0000000..6a976cb
--- /dev/null
+++ b/examples/statemachine/pauseandresume/pauseandresume.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
diff --git a/examples/statemachine/pingpong/main.cpp b/examples/statemachine/pingpong/main.cpp
new file mode 100644
index 0000000..d749076
--- /dev/null
+++ b/examples/statemachine/pingpong/main.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <stdio.h>
+#ifdef QT_STATEMACHINE_SOLUTION
+#include <qstate.h>
+#include <qstatemachine.h>
+#include <qtransition.h>
+#endif
+
+class PingEvent : public QEvent
+{
+public:
+ PingEvent() : QEvent(QEvent::Type(QEvent::User+2))
+ {}
+};
+
+class PongEvent : public QEvent
+{
+public:
+ PongEvent() : QEvent(QEvent::Type(QEvent::User+3))
+ {}
+};
+
+class Pinger : public QState
+{
+public:
+ Pinger(QStateMachine *machine, QState *parent)
+ : QState(parent), m_machine(machine) {}
+
+protected:
+ virtual void onEntry()
+ {
+ m_machine->postEvent(new PingEvent());
+ fprintf(stdout, "ping?\n");
+ }
+
+private:
+ QStateMachine *m_machine;
+};
+
+class PongTransition : public QAbstractTransition
+{
+public:
+ PongTransition(QStateMachine *machine)
+ : QAbstractTransition(), m_machine(machine) {}
+
+protected:
+ virtual bool eventTest(QEvent *e) const {
+ return (e->type() == QEvent::User+3);
+ }
+ virtual void onTransition()
+ {
+ m_machine->postEvent(new PingEvent(), 500);
+ fprintf(stdout, "ping?\n");
+ }
+
+private:
+ QStateMachine *m_machine;
+};
+
+class PingTransition : public QAbstractTransition
+{
+public:
+ PingTransition(QStateMachine *machine)
+ : QAbstractTransition(), m_machine(machine) {}
+
+protected:
+ virtual bool eventTest(QEvent *e) const {
+ return (e->type() == QEvent::User+2);
+ }
+ virtual void onTransition()
+ {
+ m_machine->postEvent(new PongEvent(), 500);
+ fprintf(stdout, "pong!\n");
+ }
+
+private:
+ QStateMachine *m_machine;
+};
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QStateMachine machine;
+ QState *group = new QState(QState::ParallelGroup);
+ group->setObjectName("group");
+
+ Pinger *pinger = new Pinger(&machine, group);
+ pinger->setObjectName("pinger");
+ pinger->addTransition(new PongTransition(&machine));
+
+ QState *ponger = new QState(group);
+ ponger->setObjectName("ponger");
+ ponger->addTransition(new PingTransition(&machine));
+
+ machine.addState(group);
+ machine.setInitialState(group);
+ machine.start();
+
+ return app.exec();
+}
diff --git a/examples/statemachine/pingpong/pingpong.pro b/examples/statemachine/pingpong/pingpong.pro
new file mode 100644
index 0000000..bff9cb8
--- /dev/null
+++ b/examples/statemachine/pingpong/pingpong.pro
@@ -0,0 +1,10 @@
+QT = core
+TEMPLATE = app
+TARGET =
+win32: CONFIG += console
+mac:CONFIG -= app_bundle
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp
diff --git a/examples/statemachine/statemachine.pro b/examples/statemachine/statemachine.pro
new file mode 100644
index 0000000..ba32c12
--- /dev/null
+++ b/examples/statemachine/statemachine.pro
@@ -0,0 +1,17 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ clockticking \
+ composition \
+ eventtransitions \
+ factorial \
+ helloworld \
+ pauseandresume \
+ pingpong \
+ trafficlight \
+ twowaybutton
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS statemachine.pro README
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine
+INSTALLS += target sources
diff --git a/examples/statemachine/trafficlight/main.cpp b/examples/statemachine/trafficlight/main.cpp
new file mode 100644
index 0000000..fbb6b68
--- /dev/null
+++ b/examples/statemachine/trafficlight/main.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#ifdef QT_STATEMACHINE_SOLUTION
+#include <qstate.h>
+#include <qstatemachine.h>
+#include <qfinalstate.h>
+#endif
+
+//! [0]
+class LightWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(bool on READ isOn WRITE setOn)
+public:
+ LightWidget(const QColor &color, QWidget *parent = 0)
+ : QWidget(parent), m_color(color), m_on(false) {}
+
+ bool isOn() const
+ { return m_on; }
+ void setOn(bool on)
+ {
+ if (on == m_on)
+ return;
+ m_on = on;
+ update();
+ }
+
+protected:
+ virtual void paintEvent(QPaintEvent *)
+ {
+ if (!m_on)
+ return;
+ QPainter painter(this);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setBrush(m_color);
+ painter.drawEllipse(0, 0, width(), height());
+ }
+
+private:
+ QColor m_color;
+ bool m_on;
+};
+//! [0]
+
+//! [1]
+class LightState : public QState
+{
+public:
+ LightState(LightWidget *light, int duration, QState *parent = 0)
+ : QState(parent)
+ {
+ QTimer *timer = new QTimer(this);
+ timer->setInterval(duration);
+ timer->setSingleShot(true);
+ QState *timing = new QState(this);
+ timing->setPropertyOnEntry(light, "on", true);
+ timing->invokeMethodOnEntry(timer, "start");
+ timing->setPropertyOnExit(light, "on", false);
+ QFinalState *done = new QFinalState(this);
+ timing->addTransition(timer, SIGNAL(timeout()), done);
+ setInitialState(timing);
+ }
+};
+//! [1]
+
+//! [2]
+class TrafficLightWidget : public QWidget
+{
+public:
+ TrafficLightWidget(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ QVBoxLayout *vbox = new QVBoxLayout(this);
+ m_red = new LightWidget(Qt::red);
+ vbox->addWidget(m_red);
+ m_yellow = new LightWidget(Qt::yellow);
+ vbox->addWidget(m_yellow);
+ m_green = new LightWidget(Qt::green);
+ vbox->addWidget(m_green);
+ QPalette pal = palette();
+ pal.setColor(QPalette::Background, Qt::black);
+ setPalette(pal);
+ setAutoFillBackground(true);
+ }
+
+ LightWidget *redLight() const
+ { return m_red; }
+ LightWidget *yellowLight() const
+ { return m_yellow; }
+ LightWidget *greenLight() const
+ { return m_green; }
+
+private:
+ LightWidget *m_red;
+ LightWidget *m_yellow;
+ LightWidget *m_green;
+};
+//! [2]
+
+//! [3]
+class TrafficLight : public QWidget
+{
+public:
+ TrafficLight(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ QVBoxLayout *vbox = new QVBoxLayout(this);
+ TrafficLightWidget *widget = new TrafficLightWidget();
+ vbox->addWidget(widget);
+
+ QStateMachine *machine = new QStateMachine(this);
+ LightState *redGoingYellow = new LightState(widget->redLight(), 3000);
+ redGoingYellow->setObjectName("redGoingYellow");
+ LightState *yellowGoingGreen = new LightState(widget->yellowLight(), 1000);
+ yellowGoingGreen->setObjectName("yellowGoingGreen");
+ redGoingYellow->addFinishedTransition(yellowGoingGreen);
+ LightState *greenGoingYellow = new LightState(widget->greenLight(), 3000);
+ greenGoingYellow->setObjectName("greenGoingYellow");
+ yellowGoingGreen->addFinishedTransition(greenGoingYellow);
+ LightState *yellowGoingRed = new LightState(widget->yellowLight(), 1000);
+ yellowGoingRed->setObjectName("yellowGoingRed");
+ greenGoingYellow->addFinishedTransition(yellowGoingRed);
+ yellowGoingRed->addFinishedTransition(redGoingYellow);
+
+ machine->addState(redGoingYellow);
+ machine->addState(yellowGoingGreen);
+ machine->addState(greenGoingYellow);
+ machine->addState(yellowGoingRed);
+ machine->setInitialState(redGoingYellow);
+ machine->start();
+ }
+};
+//! [3]
+
+//! [4]
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ TrafficLight widget;
+ widget.resize(120, 300);
+ widget.show();
+
+ return app.exec();
+}
+//! [4]
+
+#include "main.moc"
diff --git a/examples/statemachine/trafficlight/trafficlight.pro b/examples/statemachine/trafficlight/trafficlight.pro
new file mode 100644
index 0000000..730bd75
--- /dev/null
+++ b/examples/statemachine/trafficlight/trafficlight.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+SOURCES += main.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/trafficlight
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS trafficlight.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/trafficlight
+INSTALLS += target sources
diff --git a/examples/statemachine/twowaybutton/main.cpp b/examples/statemachine/twowaybutton/main.cpp
new file mode 100644
index 0000000..eab0b3d
--- /dev/null
+++ b/examples/statemachine/twowaybutton/main.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#ifdef QT_STATEMACHINE_SOLUTION
+#include <qstate.h>
+#include <qstatemachine.h>
+#endif
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QPushButton button;
+
+ QStateMachine machine;
+ QState *first = new QState();
+ first->setObjectName("first");
+
+ QState *off = new QState();
+ off->setPropertyOnEntry(&button, "text", "Off");
+ off->setObjectName("off");
+ first->addTransition(off);
+
+ QState *on = new QState();
+ on->setObjectName("on");
+ on->setPropertyOnEntry(&button, "text", "On");
+ off->addTransition(&button, SIGNAL(clicked()), on);
+ on->addTransition(&button, SIGNAL(clicked()), off);
+
+ machine.addState(first);
+ machine.addState(off);
+ machine.addState(on);
+ machine.setInitialState(first);
+ machine.start();
+
+ button.resize(100, 50);
+ button.show();
+ return app.exec();
+}
diff --git a/examples/statemachine/twowaybutton/twowaybutton.pro b/examples/statemachine/twowaybutton/twowaybutton.pro
new file mode 100644
index 0000000..6a976cb
--- /dev/null
+++ b/examples/statemachine/twowaybutton/twowaybutton.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp